(steps, summaryText)
| 279 | |
| 280 | // Derive the five validation gates from progress/summary step titles. |
| 281 | function deriveGates(steps, summaryText) { |
| 282 | const patterns = { |
| 283 | build: /\bbuild\b|compil/i, |
| 284 | tests: /unit test|\btests?\b|junit/i, |
| 285 | cve: /\bcve\b|vulnerab|security scan/i, |
| 286 | consistency: /consistenc/i, |
| 287 | completeness: /completenes/i, |
| 288 | }; |
| 289 | const gates = {}; |
| 290 | for (const g of VALIDATION_GATES) { |
| 291 | let status = "not_run"; |
| 292 | for (const s of steps) { |
| 293 | if (patterns[g.key].test(s.title)) { |
| 294 | status = s.status; // done | in_progress | failed | pending |
| 295 | break; |
| 296 | } |
| 297 | } |
| 298 | if (status === "not_run" && summaryText) { |
| 299 | const line = summaryText |
| 300 | .split(/\r?\n/) |
| 301 | .find((l) => patterns[g.key].test(l)); |
| 302 | if (line) status = statusFromText(line) || "in_progress"; |
| 303 | } |
| 304 | gates[g.key] = status; |
| 305 | } |
| 306 | return gates; |
| 307 | } |
| 308 | |
| 309 | async function discoverSkills(repoPath) { |
| 310 | const skillsDir = join(repoPath, ".github", "skills"); |
no test coverage detected