@kevinrabun/judges 3.48.0 → 3.49.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.
Files changed (38) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/cli.d.ts.map +1 -1
  3. package/dist/cli.js +56 -0
  4. package/dist/cli.js.map +1 -1
  5. package/dist/commands/incident-response.d.ts +8 -0
  6. package/dist/commands/incident-response.d.ts.map +1 -0
  7. package/dist/commands/incident-response.js +255 -0
  8. package/dist/commands/incident-response.js.map +1 -0
  9. package/dist/commands/learning-path.d.ts +9 -0
  10. package/dist/commands/learning-path.d.ts.map +1 -0
  11. package/dist/commands/learning-path.js +326 -0
  12. package/dist/commands/learning-path.js.map +1 -0
  13. package/dist/commands/license-scan.d.ts +9 -0
  14. package/dist/commands/license-scan.d.ts.map +1 -0
  15. package/dist/commands/license-scan.js +180 -0
  16. package/dist/commands/license-scan.js.map +1 -0
  17. package/dist/commands/org-policy.d.ts +8 -0
  18. package/dist/commands/org-policy.d.ts.map +1 -0
  19. package/dist/commands/org-policy.js +208 -0
  20. package/dist/commands/org-policy.js.map +1 -0
  21. package/dist/commands/predict.d.ts +8 -0
  22. package/dist/commands/predict.d.ts.map +1 -0
  23. package/dist/commands/predict.js +219 -0
  24. package/dist/commands/predict.js.map +1 -0
  25. package/dist/commands/risk-heatmap.d.ts +8 -0
  26. package/dist/commands/risk-heatmap.d.ts.map +1 -0
  27. package/dist/commands/risk-heatmap.js +224 -0
  28. package/dist/commands/risk-heatmap.js.map +1 -0
  29. package/dist/commands/sbom-export.d.ts +8 -0
  30. package/dist/commands/sbom-export.d.ts.map +1 -0
  31. package/dist/commands/sbom-export.js +162 -0
  32. package/dist/commands/sbom-export.js.map +1 -0
  33. package/dist/commands/test-correlate.d.ts +8 -0
  34. package/dist/commands/test-correlate.d.ts.map +1 -0
  35. package/dist/commands/test-correlate.js +222 -0
  36. package/dist/commands/test-correlate.js.map +1 -0
  37. package/package.json +1 -1
  38. package/server.json +2 -2
@@ -0,0 +1,255 @@
1
+ /**
2
+ * Incident response — generates incident response playbooks
3
+ * from finding spikes, CVEs, or severity escalations.
4
+ *
5
+ * All data from local files.
6
+ */
7
+ import { existsSync, readFileSync, mkdirSync, writeFileSync } from "fs";
8
+ import { join } from "path";
9
+ // ─── Playbook Generation ────────────────────────────────────────────────────
10
+ function generatePlaybook(severity, findings) {
11
+ const steps = [
12
+ {
13
+ order: 1,
14
+ action: "Acknowledge incident and assign incident commander",
15
+ owner: "security-lead",
16
+ status: "pending",
17
+ },
18
+ {
19
+ order: 2,
20
+ action: "Assess blast radius — identify all affected files and services",
21
+ owner: "incident-commander",
22
+ status: "pending",
23
+ },
24
+ {
25
+ order: 3,
26
+ action: "Notify relevant code owners and stakeholders",
27
+ owner: "incident-commander",
28
+ status: "pending",
29
+ },
30
+ ];
31
+ if (severity === "critical") {
32
+ steps.push({
33
+ order: 4,
34
+ action: "Evaluate if production rollback or hotfix is needed",
35
+ owner: "engineering-lead",
36
+ status: "pending",
37
+ }, { order: 5, action: "Apply emergency patches to critical findings", owner: "assigned-devs", status: "pending" }, { order: 6, action: "Run security regression tests on patched code", owner: "qa-lead", status: "pending" }, { order: 7, action: "Deploy hotfix through expedited release process", owner: "devops-lead", status: "pending" });
38
+ }
39
+ else {
40
+ steps.push({
41
+ order: 4,
42
+ action: "Prioritize findings by severity and blast radius",
43
+ owner: "security-lead",
44
+ status: "pending",
45
+ }, { order: 5, action: "Create fix PRs for each affected file", owner: "assigned-devs", status: "pending" }, { order: 6, action: "Review and merge fixes through normal PR process", owner: "code-owners", status: "pending" });
46
+ }
47
+ const hasSqlFindings = findings.some((f) => /sql/i.test(f.ruleId) || /injection/i.test(f.title));
48
+ if (hasSqlFindings) {
49
+ steps.push({
50
+ order: steps.length + 1,
51
+ action: "Audit database access logs for exploitation evidence",
52
+ owner: "dba",
53
+ status: "pending",
54
+ });
55
+ }
56
+ const hasAuthFindings = findings.some((f) => /auth/i.test(f.ruleId) || /auth/i.test(f.title));
57
+ if (hasAuthFindings) {
58
+ steps.push({
59
+ order: steps.length + 1,
60
+ action: "Review authentication logs and rotate affected credentials",
61
+ owner: "security-lead",
62
+ status: "pending",
63
+ });
64
+ }
65
+ steps.push({
66
+ order: steps.length + 1,
67
+ action: "Verify all findings are resolved with re-scan",
68
+ owner: "security-lead",
69
+ status: "pending",
70
+ }, {
71
+ order: steps.length + 2,
72
+ action: "Document lessons learned and update prevention controls",
73
+ owner: "incident-commander",
74
+ status: "pending",
75
+ }, {
76
+ order: steps.length + 3,
77
+ action: "Close incident and update status",
78
+ owner: "incident-commander",
79
+ status: "pending",
80
+ });
81
+ return steps;
82
+ }
83
+ function generateId() {
84
+ return `INC-${Date.now().toString(36).toUpperCase()}`;
85
+ }
86
+ // ─── Load findings ──────────────────────────────────────────────────────────
87
+ function loadRecentFindings() {
88
+ const paths = [".judges-findings.json", "judges-report.json"];
89
+ for (const p of paths) {
90
+ if (!existsSync(p))
91
+ continue;
92
+ try {
93
+ const data = JSON.parse(readFileSync(p, "utf-8"));
94
+ if (Array.isArray(data))
95
+ return data;
96
+ if (data.findings)
97
+ return data.findings;
98
+ }
99
+ catch {
100
+ /* skip */
101
+ }
102
+ }
103
+ return [];
104
+ }
105
+ // ─── CLI ────────────────────────────────────────────────────────────────────
106
+ const STORE = ".judges-incidents";
107
+ export function runIncidentResponse(argv) {
108
+ if (argv.includes("--help") || argv.includes("-h")) {
109
+ console.log(`
110
+ judges incident-response — Incident response playbook generation
111
+
112
+ Usage:
113
+ judges incident-response --create --severity critical --title "SQL Injection in auth module"
114
+ judges incident-response --list
115
+ judges incident-response --show <id>
116
+ judges incident-response --update <id> --status investigating
117
+ judges incident-response --generate-from-findings
118
+
119
+ Options:
120
+ --create Create new incident
121
+ --severity <level> Incident severity (critical, high, medium)
122
+ --title <text> Incident title
123
+ --generate-from-findings Auto-generate incident from current findings
124
+ --list List all incidents
125
+ --show <id> Show incident details
126
+ --update <id> Update incident
127
+ --status <status> Set status (open, investigating, mitigating, resolved)
128
+ --format json JSON output
129
+ --help, -h Show this help
130
+ `);
131
+ return;
132
+ }
133
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
134
+ if (!existsSync(STORE))
135
+ mkdirSync(STORE, { recursive: true });
136
+ const incidentsPath = join(STORE, "incidents.json");
137
+ const incidents = existsSync(incidentsPath) ? JSON.parse(readFileSync(incidentsPath, "utf-8")) : [];
138
+ // List
139
+ if (argv.includes("--list")) {
140
+ if (format === "json") {
141
+ console.log(JSON.stringify(incidents, null, 2));
142
+ }
143
+ else {
144
+ console.log(`\n Incidents (${incidents.length})\n ──────────────────────────`);
145
+ if (incidents.length === 0) {
146
+ console.log(" No incidents recorded.\n");
147
+ return;
148
+ }
149
+ for (const inc of incidents) {
150
+ console.log(` [${inc.status.toUpperCase().padEnd(13)}] ${inc.id} ${inc.severity.toUpperCase().padEnd(8)} ${inc.title}`);
151
+ }
152
+ console.log("");
153
+ }
154
+ return;
155
+ }
156
+ // Show
157
+ const showId = argv.find((_a, i) => argv[i - 1] === "--show");
158
+ if (showId) {
159
+ const inc = incidents.find((i) => i.id === showId);
160
+ if (!inc) {
161
+ console.error(` Incident ${showId} not found.`);
162
+ return;
163
+ }
164
+ if (format === "json") {
165
+ console.log(JSON.stringify(inc, null, 2));
166
+ }
167
+ else {
168
+ console.log(`\n Incident: ${inc.id}\n ──────────────────────────`);
169
+ console.log(` Title: ${inc.title}`);
170
+ console.log(` Severity: ${inc.severity}`);
171
+ console.log(` Status: ${inc.status}`);
172
+ console.log(` Created: ${inc.createdAt}`);
173
+ console.log(` Files: ${inc.affectedFiles.length}`);
174
+ console.log(` Findings: ${inc.findings.length}`);
175
+ console.log(`\n Playbook:`);
176
+ for (const step of inc.playbook) {
177
+ const icon = step.status === "done" ? "✅" : step.status === "in-progress" ? "🔄" : "⬜";
178
+ console.log(` ${icon} ${step.order}. ${step.action} (@${step.owner})`);
179
+ }
180
+ console.log("");
181
+ }
182
+ return;
183
+ }
184
+ // Update
185
+ const updateId = argv.find((_a, i) => argv[i - 1] === "--update");
186
+ if (updateId) {
187
+ const inc = incidents.find((i) => i.id === updateId);
188
+ if (!inc) {
189
+ console.error(` Incident ${updateId} not found.`);
190
+ return;
191
+ }
192
+ const newStatus = argv.find((_a, i) => argv[i - 1] === "--status");
193
+ if (newStatus) {
194
+ inc.status = newStatus;
195
+ inc.updatedAt = new Date().toISOString();
196
+ writeFileSync(incidentsPath, JSON.stringify(incidents, null, 2));
197
+ console.log(` Incident ${updateId} → ${newStatus}`);
198
+ }
199
+ return;
200
+ }
201
+ // Generate from findings
202
+ if (argv.includes("--generate-from-findings")) {
203
+ const findings = loadRecentFindings();
204
+ const criticals = findings.filter((f) => f.severity === "critical");
205
+ const highs = findings.filter((f) => f.severity === "high");
206
+ if (criticals.length === 0 && highs.length === 0) {
207
+ console.log(" No critical or high severity findings to generate incident from.");
208
+ return;
209
+ }
210
+ const severity = criticals.length > 0 ? "critical" : "high";
211
+ const relevantFindings = criticals.length > 0 ? criticals : highs;
212
+ const affectedFiles = [...new Set(relevantFindings.map((f) => f.file || "unknown"))];
213
+ const incident = {
214
+ id: generateId(),
215
+ severity,
216
+ title: `${severity.toUpperCase()} findings detected (${relevantFindings.length})`,
217
+ description: `Auto-generated incident from ${relevantFindings.length} ${severity} severity findings`,
218
+ affectedFiles,
219
+ findings: relevantFindings.map((f) => ({ ruleId: f.ruleId, severity: f.severity, title: f.title })),
220
+ playbook: generatePlaybook(severity, relevantFindings),
221
+ status: "open",
222
+ createdAt: new Date().toISOString(),
223
+ updatedAt: new Date().toISOString(),
224
+ };
225
+ incidents.push(incident);
226
+ writeFileSync(incidentsPath, JSON.stringify(incidents, null, 2));
227
+ console.log(` Created incident ${incident.id} (${severity}) with ${incident.playbook.length}-step playbook`);
228
+ return;
229
+ }
230
+ // Create
231
+ if (argv.includes("--create")) {
232
+ const severity = (argv.find((_a, i) => argv[i - 1] === "--severity") ||
233
+ "high");
234
+ const title = argv.find((_a, i) => argv[i - 1] === "--title") || "New security incident";
235
+ const findings = loadRecentFindings();
236
+ const incident = {
237
+ id: generateId(),
238
+ severity,
239
+ title,
240
+ description: `Manually created incident: ${title}`,
241
+ affectedFiles: [...new Set(findings.map((f) => f.file || "unknown"))],
242
+ findings: findings.map((f) => ({ ruleId: f.ruleId, severity: f.severity, title: f.title })),
243
+ playbook: generatePlaybook(severity, findings),
244
+ status: "open",
245
+ createdAt: new Date().toISOString(),
246
+ updatedAt: new Date().toISOString(),
247
+ };
248
+ incidents.push(incident);
249
+ writeFileSync(incidentsPath, JSON.stringify(incidents, null, 2));
250
+ console.log(` Created incident ${incident.id} with ${incident.playbook.length}-step playbook`);
251
+ return;
252
+ }
253
+ console.log(" Use --create, --generate-from-findings, --list, --show, or --update. Run --help for details.");
254
+ }
255
+ //# sourceMappingURL=incident-response.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"incident-response.js","sourceRoot":"","sources":["../../src/commands/incident-response.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Learning path — generates personalized developer learning
3
+ * modules from recurring finding patterns, tracking skill
4
+ * progression over time.
5
+ *
6
+ * All data stored locally.
7
+ */
8
+ export declare function runLearningPath(argv: string[]): void;
9
+ //# sourceMappingURL=learning-path.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"learning-path.d.ts","sourceRoot":"","sources":["../../src/commands/learning-path.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAgNH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CA4JpD"}
@@ -0,0 +1,326 @@
1
+ /**
2
+ * Learning path — generates personalized developer learning
3
+ * modules from recurring finding patterns, tracking skill
4
+ * progression over time.
5
+ *
6
+ * All data stored locally.
7
+ */
8
+ import { existsSync, readFileSync, mkdirSync, writeFileSync } from "fs";
9
+ import { join } from "path";
10
+ // ─── Module Library ─────────────────────────────────────────────────────────
11
+ const MODULES = [
12
+ {
13
+ id: "sql-injection-101",
14
+ topic: "SQL Injection Prevention",
15
+ difficulty: "beginner",
16
+ description: "Learn to identify and prevent SQL injection vulnerabilities",
17
+ resources: [
18
+ "OWASP SQL Injection Prevention Cheat Sheet",
19
+ "Use parameterized queries instead of string concatenation",
20
+ "Apply input validation at system boundaries",
21
+ ],
22
+ exercises: [
23
+ "Refactor a string-concatenated query to use parameterized statements",
24
+ "Identify SQL injection vectors in a sample CRUD controller",
25
+ "Implement an ORM-based data access layer",
26
+ ],
27
+ prerequisites: [],
28
+ },
29
+ {
30
+ id: "xss-prevention",
31
+ topic: "Cross-Site Scripting (XSS) Prevention",
32
+ difficulty: "beginner",
33
+ description: "Understand and prevent XSS vulnerabilities in web applications",
34
+ resources: [
35
+ "OWASP XSS Prevention Cheat Sheet",
36
+ "Content Security Policy (CSP) headers",
37
+ "Output encoding for different contexts (HTML, JS, URL, CSS)",
38
+ ],
39
+ exercises: [
40
+ "Add output encoding to a template rendering user input",
41
+ "Configure CSP headers for a web application",
42
+ "Test for DOM-based XSS in a client-side application",
43
+ ],
44
+ prerequisites: [],
45
+ },
46
+ {
47
+ id: "auth-security",
48
+ topic: "Authentication & Authorization",
49
+ difficulty: "intermediate",
50
+ description: "Implement secure authentication and authorization patterns",
51
+ resources: [
52
+ "OWASP Authentication Cheat Sheet",
53
+ "JWT best practices and pitfalls",
54
+ "OAuth 2.0 and OpenID Connect fundamentals",
55
+ ],
56
+ exercises: [
57
+ "Implement rate limiting on login endpoints",
58
+ "Add proper JWT validation with signature verification",
59
+ "Design role-based access control for an API",
60
+ ],
61
+ prerequisites: ["sql-injection-101"],
62
+ },
63
+ {
64
+ id: "crypto-basics",
65
+ topic: "Cryptography Fundamentals",
66
+ difficulty: "intermediate",
67
+ description: "Use cryptographic primitives correctly",
68
+ resources: [
69
+ "OWASP Cryptographic Storage Cheat Sheet",
70
+ "Modern cipher suites and key management",
71
+ "Password hashing: bcrypt, scrypt, Argon2",
72
+ ],
73
+ exercises: [
74
+ "Replace MD5/SHA-1 with SHA-256 or better",
75
+ "Implement proper password hashing with Argon2",
76
+ "Set up encrypted-at-rest storage for sensitive data",
77
+ ],
78
+ prerequisites: [],
79
+ },
80
+ {
81
+ id: "ssrf-prevention",
82
+ topic: "Server-Side Request Forgery (SSRF)",
83
+ difficulty: "advanced",
84
+ description: "Prevent SSRF attacks in web applications",
85
+ resources: [
86
+ "OWASP SSRF Prevention Cheat Sheet",
87
+ "URL validation and allowlisting strategies",
88
+ "Network segmentation for defense in depth",
89
+ ],
90
+ exercises: [
91
+ "Implement URL validation with an allowlist",
92
+ "Block internal IP ranges in outbound requests",
93
+ "Design a secure proxy service for external API calls",
94
+ ],
95
+ prerequisites: ["auth-security"],
96
+ },
97
+ {
98
+ id: "supply-chain",
99
+ topic: "Supply Chain Security",
100
+ difficulty: "advanced",
101
+ description: "Secure the software supply chain",
102
+ resources: [
103
+ "SLSA framework for supply chain integrity",
104
+ "Dependency pinning and lock file management",
105
+ "SBOM generation and consumption",
106
+ ],
107
+ exercises: [
108
+ "Generate an SBOM with `judges sbom-export`",
109
+ "Audit dependencies with `judges dep-correlate`",
110
+ "Set up automated dependency update policies",
111
+ ],
112
+ prerequisites: ["crypto-basics"],
113
+ },
114
+ {
115
+ id: "secure-code-review",
116
+ topic: "Secure Code Review Practices",
117
+ difficulty: "intermediate",
118
+ description: "Conduct effective security-focused code reviews",
119
+ resources: [
120
+ "OWASP Code Review Guide",
121
+ "Common vulnerability patterns by language",
122
+ "Using Judges for automated security review",
123
+ ],
124
+ exercises: [
125
+ "Review a sample PR for security issues using Judges",
126
+ "Create a custom judge with `judges judge-author`",
127
+ "Build a team pattern library with `judges pattern-registry`",
128
+ ],
129
+ prerequisites: ["sql-injection-101", "xss-prevention"],
130
+ },
131
+ {
132
+ id: "incident-handling",
133
+ topic: "Security Incident Handling",
134
+ difficulty: "advanced",
135
+ description: "Respond to and manage security incidents",
136
+ resources: [
137
+ "NIST Incident Response Guide",
138
+ "Post-incident review best practices",
139
+ "Using `judges incident-response` for playbook generation",
140
+ ],
141
+ exercises: [
142
+ "Create an incident response playbook for a critical finding",
143
+ "Conduct a tabletop exercise with the team",
144
+ "Set up SLA tracking with `judges sla-track`",
145
+ ],
146
+ prerequisites: ["secure-code-review", "auth-security"],
147
+ },
148
+ ];
149
+ // ─── Analysis ───────────────────────────────────────────────────────────────
150
+ const TOPIC_PATTERNS = {
151
+ "SQL Injection Prevention": ["sql", "injection", "query", "database"],
152
+ "Cross-Site Scripting (XSS) Prevention": ["xss", "cross-site", "script", "sanitize", "encode"],
153
+ "Authentication & Authorization": ["auth", "login", "password", "token", "jwt", "session", "rbac"],
154
+ "Cryptography Fundamentals": ["crypto", "cipher", "hash", "encrypt", "md5", "sha1", "key"],
155
+ "Server-Side Request Forgery (SSRF)": ["ssrf", "request-forgery", "url", "redirect"],
156
+ "Supply Chain Security": ["dependency", "package", "npm", "supply-chain", "sbom"],
157
+ "Secure Code Review Practices": ["review", "code-quality", "pattern"],
158
+ "Security Incident Handling": ["incident", "breach", "response", "escalation"],
159
+ };
160
+ function analyzeWeaknesses(findings) {
161
+ const topicCounts = new Map();
162
+ for (const f of findings) {
163
+ const text = `${f.ruleId} ${f.title}`.toLowerCase();
164
+ for (const [topic, patterns] of Object.entries(TOPIC_PATTERNS)) {
165
+ if (patterns.some((p) => text.includes(p))) {
166
+ topicCounts.set(topic, (topicCounts.get(topic) || 0) + 1);
167
+ }
168
+ }
169
+ }
170
+ return [...topicCounts.entries()]
171
+ .map(([topic, count]) => ({ topic, findingCount: count }))
172
+ .sort((a, b) => b.findingCount - a.findingCount);
173
+ }
174
+ // ─── CLI ────────────────────────────────────────────────────────────────────
175
+ const STORE = ".judges-learning";
176
+ export function runLearningPath(argv) {
177
+ if (argv.includes("--help") || argv.includes("-h")) {
178
+ console.log(`
179
+ judges learning-path — Personalized security learning recommendations
180
+
181
+ Usage:
182
+ judges learning-path
183
+ judges learning-path --developer "alice"
184
+ judges learning-path --modules
185
+ judges learning-path --complete <module-id>
186
+
187
+ Options:
188
+ --developer <name> Developer name for personalized path
189
+ --modules List all available learning modules
190
+ --complete <id> Mark a module as completed
191
+ --reset Reset progress for developer
192
+ --format json JSON output
193
+ --help, -h Show this help
194
+ `);
195
+ return;
196
+ }
197
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
198
+ // List modules
199
+ if (argv.includes("--modules")) {
200
+ if (format === "json") {
201
+ console.log(JSON.stringify(MODULES, null, 2));
202
+ }
203
+ else {
204
+ console.log(`\n Learning Modules (${MODULES.length})\n ──────────────────────────`);
205
+ for (const m of MODULES) {
206
+ console.log(` [${m.difficulty.padEnd(12)}] ${m.id.padEnd(25)} ${m.topic}`);
207
+ }
208
+ console.log("");
209
+ }
210
+ return;
211
+ }
212
+ if (!existsSync(STORE))
213
+ mkdirSync(STORE, { recursive: true });
214
+ const devName = argv.find((_a, i) => argv[i - 1] === "--developer") || "default";
215
+ const progressPath = join(STORE, `${devName}-progress.json`);
216
+ let progress = existsSync(progressPath)
217
+ ? JSON.parse(readFileSync(progressPath, "utf-8"))
218
+ : { developer: devName, completedModules: [], weakAreas: [], skillLevel: 1, lastUpdated: new Date().toISOString() };
219
+ // Reset
220
+ if (argv.includes("--reset")) {
221
+ progress = {
222
+ developer: devName,
223
+ completedModules: [],
224
+ weakAreas: [],
225
+ skillLevel: 1,
226
+ lastUpdated: new Date().toISOString(),
227
+ };
228
+ writeFileSync(progressPath, JSON.stringify(progress, null, 2));
229
+ console.log(` Reset progress for ${devName}`);
230
+ return;
231
+ }
232
+ // Complete module
233
+ const completeId = argv.find((_a, i) => argv[i - 1] === "--complete");
234
+ if (completeId) {
235
+ const mod = MODULES.find((m) => m.id === completeId);
236
+ if (!mod) {
237
+ console.error(` Module ${completeId} not found.`);
238
+ return;
239
+ }
240
+ if (!progress.completedModules.includes(completeId)) {
241
+ progress.completedModules.push(completeId);
242
+ progress.skillLevel = Math.min(10, Math.round((progress.completedModules.length / MODULES.length) * 10));
243
+ progress.lastUpdated = new Date().toISOString();
244
+ writeFileSync(progressPath, JSON.stringify(progress, null, 2));
245
+ }
246
+ console.log(` Completed: ${mod.topic} — Skill level: ${progress.skillLevel}/10`);
247
+ return;
248
+ }
249
+ // Analyze and recommend
250
+ const findings = [];
251
+ const paths = [".judges-findings.json", "judges-report.json"];
252
+ for (const p of paths) {
253
+ if (!existsSync(p))
254
+ continue;
255
+ try {
256
+ const data = JSON.parse(readFileSync(p, "utf-8"));
257
+ if (Array.isArray(data))
258
+ findings.push(...data);
259
+ else if (data.findings)
260
+ findings.push(...data.findings);
261
+ }
262
+ catch {
263
+ /* skip */
264
+ }
265
+ }
266
+ const weakAreas = analyzeWeaknesses(findings);
267
+ progress.weakAreas = weakAreas;
268
+ progress.lastUpdated = new Date().toISOString();
269
+ writeFileSync(progressPath, JSON.stringify(progress, null, 2));
270
+ // Find recommended modules (not completed, prerequisites met)
271
+ const recommended = MODULES.filter((m) => {
272
+ if (progress.completedModules.includes(m.id))
273
+ return false;
274
+ const prereqsMet = m.prerequisites.every((p) => progress.completedModules.includes(p));
275
+ if (!prereqsMet)
276
+ return false;
277
+ // Prioritize modules matching weak areas
278
+ return true;
279
+ });
280
+ // Sort by relevance to weak areas
281
+ const sortedRecs = recommended.sort((a, b) => {
282
+ const aRelevance = weakAreas.find((w) => w.topic === a.topic)?.findingCount || 0;
283
+ const bRelevance = weakAreas.find((w) => w.topic === b.topic)?.findingCount || 0;
284
+ return bRelevance - aRelevance;
285
+ });
286
+ const report = {
287
+ recommendedModules: sortedRecs,
288
+ progress,
289
+ timestamp: new Date().toISOString(),
290
+ };
291
+ if (format === "json") {
292
+ console.log(JSON.stringify(report, null, 2));
293
+ }
294
+ else {
295
+ console.log(`\n Learning Path — ${devName}`);
296
+ console.log(` Skill Level: ${progress.skillLevel}/10 Completed: ${progress.completedModules.length}/${MODULES.length}`);
297
+ console.log(` ──────────────────────────`);
298
+ if (weakAreas.length > 0) {
299
+ console.log(`\n Weak Areas (from findings):`);
300
+ for (const w of weakAreas.slice(0, 5)) {
301
+ console.log(` ${w.topic.padEnd(35)} ${w.findingCount} findings`);
302
+ }
303
+ }
304
+ console.log(`\n Recommended Modules:`);
305
+ if (sortedRecs.length === 0) {
306
+ console.log(` 🎉 All available modules completed!`);
307
+ }
308
+ else {
309
+ for (const m of sortedRecs.slice(0, 5)) {
310
+ const relevant = weakAreas.find((w) => w.topic === m.topic);
311
+ const tag = relevant ? ` (${relevant.findingCount} findings)` : "";
312
+ console.log(` [${m.difficulty.padEnd(12)}] ${m.id}${tag}`);
313
+ console.log(` ${m.topic}`);
314
+ }
315
+ }
316
+ if (progress.completedModules.length > 0) {
317
+ console.log(`\n Completed:`);
318
+ for (const id of progress.completedModules) {
319
+ const mod = MODULES.find((m) => m.id === id);
320
+ console.log(` ✅ ${mod?.topic || id}`);
321
+ }
322
+ }
323
+ console.log("");
324
+ }
325
+ }
326
+ //# sourceMappingURL=learning-path.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"learning-path.js","sourceRoot":"","sources":["../../src/commands/learning-path.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * License scan — scans project dependencies for license
3
+ * compatibility, flags copyleft/unknown licenses, and
4
+ * generates a license obligations report.
5
+ *
6
+ * All data from local files.
7
+ */
8
+ export declare function runLicenseScan(argv: string[]): void;
9
+ //# sourceMappingURL=license-scan.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"license-scan.d.ts","sourceRoot":"","sources":["../../src/commands/license-scan.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAiIH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAkFnD"}