@codeharbor/agent-playbook 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. package/package.json +5 -2
  2. package/skills/api-designer/README.md +36 -0
  3. package/skills/api-designer/SKILL.md +232 -0
  4. package/skills/api-designer/references/graphql-patterns.md +12 -0
  5. package/skills/api-designer/references/rest-patterns.md +17 -0
  6. package/skills/api-designer/scripts/generate_api.py +87 -0
  7. package/skills/api-designer/scripts/validate_api.py +48 -0
  8. package/skills/api-documenter/README.md +41 -0
  9. package/skills/api-documenter/SKILL.md +209 -0
  10. package/skills/api-documenter/references/examples/README.md +3 -0
  11. package/skills/api-documenter/references/examples/openapi-example.yaml +10 -0
  12. package/skills/api-documenter/references/openapi-template.yaml +5 -0
  13. package/skills/api-documenter/scripts/generate_openapi.py +84 -0
  14. package/skills/api-documenter/scripts/validate_openapi.py +45 -0
  15. package/skills/architecting-solutions/README.md +22 -0
  16. package/skills/architecting-solutions/SKILL.md +459 -0
  17. package/skills/auto-trigger/README.md +23 -0
  18. package/skills/auto-trigger/SKILL.md +183 -0
  19. package/skills/code-reviewer/README.md +59 -0
  20. package/skills/code-reviewer/SKILL.md +220 -0
  21. package/skills/code-reviewer/references/checklist.md +80 -0
  22. package/skills/code-reviewer/references/patterns.md +226 -0
  23. package/skills/code-reviewer/references/security.md +88 -0
  24. package/skills/code-reviewer/scripts/review_checklist.py +191 -0
  25. package/skills/commit-helper/README.md +58 -0
  26. package/skills/commit-helper/SKILL.md +159 -0
  27. package/skills/commit-helper/references/conventional-commits.md +68 -0
  28. package/skills/commit-helper/references/examples.md +125 -0
  29. package/skills/commit-helper/references/scopes.md +49 -0
  30. package/skills/commit-helper/scripts/validate_commit.py +70 -0
  31. package/skills/create-pr/README.md +182 -0
  32. package/skills/create-pr/SKILL.md +340 -0
  33. package/skills/debugger/README.md +53 -0
  34. package/skills/debugger/SKILL.md +239 -0
  35. package/skills/debugger/references/checklist.md +7 -0
  36. package/skills/debugger/references/errors.md +6 -0
  37. package/skills/debugger/references/patterns.md +5 -0
  38. package/skills/debugger/scripts/debug_report.py +77 -0
  39. package/skills/deployment-engineer/README.md +40 -0
  40. package/skills/deployment-engineer/SKILL.md +242 -0
  41. package/skills/deployment-engineer/references/kubernetes.md +23 -0
  42. package/skills/deployment-engineer/references/monitoring.md +14 -0
  43. package/skills/deployment-engineer/references/pipelines.md +12 -0
  44. package/skills/deployment-engineer/scripts/generate_deploy.py +72 -0
  45. package/skills/deployment-engineer/scripts/validate_deploy.py +46 -0
  46. package/skills/documentation-engineer/README.md +41 -0
  47. package/skills/documentation-engineer/SKILL.md +164 -0
  48. package/skills/documentation-engineer/references/api-template.md +22 -0
  49. package/skills/documentation-engineer/references/readme-template.md +25 -0
  50. package/skills/documentation-engineer/references/style-guide.md +13 -0
  51. package/skills/documentation-engineer/scripts/generate_docs.py +68 -0
  52. package/skills/documentation-engineer/scripts/validate_docs.py +46 -0
  53. package/skills/figma-designer/README.md +222 -0
  54. package/skills/figma-designer/SKILL.md +407 -0
  55. package/skills/figma-designer/references/example-output.md +86 -0
  56. package/skills/performance-engineer/README.md +42 -0
  57. package/skills/performance-engineer/SKILL.md +236 -0
  58. package/skills/performance-engineer/references/checklist.md +6 -0
  59. package/skills/performance-engineer/references/monitoring.md +5 -0
  60. package/skills/performance-engineer/references/optimization.md +7 -0
  61. package/skills/performance-engineer/scripts/perf_report.py +64 -0
  62. package/skills/performance-engineer/scripts/profile.py +63 -0
  63. package/skills/planning-with-files/README.md +27 -0
  64. package/skills/planning-with-files/SKILL.md +103 -0
  65. package/skills/prd-implementation-precheck/README.md +97 -0
  66. package/skills/prd-implementation-precheck/SKILL.md +112 -0
  67. package/skills/prd-planner/README.md +102 -0
  68. package/skills/prd-planner/SKILL.md +449 -0
  69. package/skills/prd-planner/references/edge-case-analysis.md +111 -0
  70. package/skills/qa-expert/README.md +37 -0
  71. package/skills/qa-expert/SKILL.md +225 -0
  72. package/skills/qa-expert/references/gates.md +11 -0
  73. package/skills/qa-expert/references/metrics.md +6 -0
  74. package/skills/qa-expert/references/strategy.md +11 -0
  75. package/skills/qa-expert/scripts/coverage_analysis.py +61 -0
  76. package/skills/qa-expert/scripts/generate_test_plan.py +68 -0
  77. package/skills/refactoring-specialist/README.md +37 -0
  78. package/skills/refactoring-specialist/SKILL.md +283 -0
  79. package/skills/refactoring-specialist/references/checklist.md +6 -0
  80. package/skills/refactoring-specialist/references/smells.md +6 -0
  81. package/skills/refactoring-specialist/references/techniques.md +6 -0
  82. package/skills/security-auditor/README.md +48 -0
  83. package/skills/security-auditor/SKILL.md +256 -0
  84. package/skills/security-auditor/references/checklist.md +7 -0
  85. package/skills/security-auditor/references/owasp.md +12 -0
  86. package/skills/security-auditor/references/remediation.md +7 -0
  87. package/skills/security-auditor/scripts/find_secrets.py +58 -0
  88. package/skills/security-auditor/scripts/security_audit.py +64 -0
  89. package/skills/self-improving-agent/README.md +136 -0
  90. package/skills/self-improving-agent/SKILL.md +407 -0
  91. package/skills/self-improving-agent/hooks/post-bash.sh +10 -0
  92. package/skills/self-improving-agent/hooks/pre-tool.sh +10 -0
  93. package/skills/self-improving-agent/hooks/session-end.sh +4 -0
  94. package/skills/self-improving-agent/memory/semantic-patterns.json +288 -0
  95. package/skills/self-improving-agent/references/appendix.md +131 -0
  96. package/skills/self-improving-agent/templates/correction-template.md +11 -0
  97. package/skills/self-improving-agent/templates/pattern-template.md +15 -0
  98. package/skills/self-improving-agent/templates/validation-template.md +14 -0
  99. package/skills/session-logger/README.md +50 -0
  100. package/skills/session-logger/SKILL.md +156 -0
  101. package/skills/skill-router/README.md +155 -0
  102. package/skills/skill-router/SKILL.md +215 -0
  103. package/skills/test-automator/README.md +41 -0
  104. package/skills/test-automator/SKILL.md +202 -0
  105. package/skills/test-automator/references/best-practices.md +6 -0
  106. package/skills/test-automator/references/examples/README.md +3 -0
  107. package/skills/test-automator/references/examples/unit-test-example.md +8 -0
  108. package/skills/test-automator/references/mocking.md +5 -0
  109. package/skills/test-automator/scripts/coverage_report.py +59 -0
  110. package/skills/test-automator/scripts/generate_test.py +66 -0
  111. package/skills/workflow-orchestrator/README.md +20 -0
  112. package/skills/workflow-orchestrator/SKILL.md +342 -0
  113. package/src/cli.js +25 -10
@@ -0,0 +1,66 @@
1
+ #!/usr/bin/env python3
2
+ # Template generator for test plan.
3
+
4
+ from pathlib import Path
5
+ import argparse
6
+ import textwrap
7
+
8
+
9
+ def write_output(path: Path, content: str, force: bool) -> bool:
10
+ if path.exists() and not force:
11
+ print(f"{path} already exists (use --force to overwrite)")
12
+ return False
13
+ path.parent.mkdir(parents=True, exist_ok=True)
14
+ path.write_text(content, encoding="utf-8")
15
+ return True
16
+
17
+
18
+ def main() -> int:
19
+ parser = argparse.ArgumentParser(description="Generate a test plan.")
20
+ parser.add_argument("--output", default="tests/test-plan.md", help="Output file path")
21
+ parser.add_argument("--name", default="example", help="Feature or release name")
22
+ parser.add_argument("--owner", default="team", help="Owning team")
23
+ parser.add_argument("--force", action="store_true", help="Overwrite existing file")
24
+ args = parser.parse_args()
25
+
26
+ content = textwrap.dedent(
27
+ f"""\
28
+ # Test Plan
29
+
30
+ ## Scope
31
+ {args.name}
32
+
33
+ ## Ownership
34
+ - Owner: {args.owner}
35
+ - QA contact: TBD
36
+
37
+ ## Scenarios
38
+ - Happy path
39
+ - Error handling
40
+ - Edge cases
41
+
42
+ ## Test Types
43
+ - Unit
44
+ - Integration
45
+ - End-to-end
46
+
47
+ ## Environments
48
+ - Local
49
+ - Staging
50
+ - Production
51
+
52
+ ## Exit Criteria
53
+ - Tests passing
54
+ - Defects triaged
55
+ """
56
+ ).strip() + "\n"
57
+
58
+ output = Path(args.output)
59
+ if not write_output(output, content, args.force):
60
+ return 1
61
+ print(f"Wrote {output}")
62
+ return 0
63
+
64
+
65
+ if __name__ == "__main__":
66
+ raise SystemExit(main())
@@ -0,0 +1,20 @@
1
+ # Workflow Orchestrator
2
+
3
+ > A Claude Code skill that coordinates multi-skill workflows using hook definitions.
4
+
5
+ ## Installation
6
+
7
+ This skill is part of the [agent-playbook](https://github.com/Charon-Fan/agent-playbook) collection.
8
+
9
+ ## Usage
10
+
11
+ ```
12
+ You: Complete workflow
13
+ You: Finish the process and trigger next steps
14
+ ```
15
+
16
+ ## How It Works
17
+
18
+ - Reads hook definitions from `skills/auto-trigger/SKILL.md`
19
+ - Executes follow-up actions based on `auto`, `background`, or `ask_first` modes
20
+ - Logs progress and context to `session-logger`
@@ -0,0 +1,342 @@
1
+ ---
2
+ name: workflow-orchestrator
3
+ description: Automatically coordinates multi-skill workflows and triggers follow-up actions. Use when completing PRD creation, implementation, or any milestone that should trigger additional skills. This skill reads the auto-trigger configuration and executes the workflow chain.
4
+ allowed-tools: Read, Write, Edit, Bash, Grep, AskUserQuestion
5
+ hooks:
6
+ after_complete:
7
+ - trigger: session-logger
8
+ mode: auto
9
+ reason: "Save workflow execution context"
10
+ ---
11
+
12
+ # Workflow Orchestrator
13
+
14
+ A skill that automatically coordinates workflows across multiple skills, triggering follow-up actions at appropriate milestones.
15
+
16
+ ## When This Skill Activates
17
+
18
+ This skill should be triggered automatically when:
19
+ - A skill completes its main workflow
20
+ - A milestone is reached (PRD complete, implementation done, etc.)
21
+ - User says "complete workflow" or "finish the process"
22
+
23
+ ## How It Works
24
+
25
+ ```
26
+ ┌─────────────────────────────────────────────────────────────┐
27
+ │ Workflow Orchestration │
28
+ ├─────────────────────────────────────────────────────────────┤
29
+ │ │
30
+ │ 1. Detect Milestone → 2. Read Hooks → 3. Execute Chain │
31
+ │ │
32
+ │ prd-planner complete │
33
+ │ ↓ │
34
+ │ workflow-orchestrator │
35
+ │ ↓ │
36
+ │ ┌─────────────────────────────────────┐ │
37
+ │ │ auto-trigger self-improving-agent │ (background) │
38
+ │ │ auto-trigger session-logger │ (auto) │
39
+ │ └─────────────────────────────────────┘ │
40
+ │ │
41
+ └─────────────────────────────────────────────────────────────┘
42
+ ```
43
+
44
+ ## Trigger Configuration
45
+
46
+ Read trigger definitions from `skills/auto-trigger/SKILL.md`:
47
+
48
+ ```yaml
49
+ hooks:
50
+ after_complete:
51
+ - trigger: self-improving-agent
52
+ mode: background
53
+ - trigger: session-logger
54
+ mode: auto
55
+ on_error:
56
+ - trigger: self-improving-agent
57
+ mode: background
58
+ ```
59
+
60
+ ## Execution Modes
61
+
62
+ | Mode | Behavior | Use When |
63
+ |------|----------|----------|
64
+ | `auto` | Execute immediately, no confirmation | Logging, status updates |
65
+ | `background` | Execute without blocking | Reflection, analysis |
66
+ | `ask_first` | Ask user before executing | PRs, deployments, major changes |
67
+
68
+ ## Milestone Detection
69
+
70
+ ### PRD Complete
71
+
72
+ ```markdown
73
+ Detected when:
74
+ - docs/{scope}-prd.md exists
75
+ - All phases in {scope}-prd-task-plan.md are checked
76
+ - Status shows "COMPLETE"
77
+
78
+ Actions:
79
+ 1. Trigger self-improving-agent (background)
80
+ 2. Trigger session-logger (auto)
81
+ ```
82
+
83
+ ### Implementation Complete
84
+
85
+ ```markdown
86
+ Detected when:
87
+ - All PRD requirements implemented
88
+ - Tests pass
89
+ - Code committed
90
+
91
+ Actions:
92
+ 1. Trigger code-reviewer (ask_first)
93
+ 2. Trigger create-pr if changes staged
94
+ 3. Trigger session-logger (auto)
95
+ ```
96
+
97
+ ### Self-Improvement Complete
98
+
99
+ ```markdown
100
+ Detected when:
101
+ - Reflection complete
102
+ - Patterns abstracted
103
+ - Skill files modified
104
+
105
+ Actions:
106
+ 1. Trigger create-pr (ask_first)
107
+ 2. Trigger session-logger (auto)
108
+ ```
109
+
110
+ ### Universal Learning (Any Skill Complete)
111
+
112
+ ```markdown
113
+ Detected when:
114
+ - ANY skill completes its workflow
115
+ - User provides feedback
116
+ - Error or issue encountered
117
+
118
+ Actions:
119
+ 1. Trigger self-improving-agent (background)
120
+ 2. Trigger session-logger (auto)
121
+
122
+ The self-improving-agent:
123
+ - Extracts experience from completed skill
124
+ - Identifies patterns and insights
125
+ - Updates related skills with learned patterns
126
+ - Consolidates memory for future reference
127
+ ```
128
+
129
+ ## Error Handling (on_error)
130
+
131
+ Detected when:
132
+ - A command returns non-zero exit code
133
+ - Tests fail after following skill guidance
134
+ - User reports the guidance produced incorrect results
135
+
136
+ Actions:
137
+ 1. Trigger self-improving-agent (background) for self-correction
138
+ 2. Trigger session-logger (auto) to capture error context
139
+
140
+ ## Hook Implementation in Skills
141
+
142
+ To enable auto-trigger, add this section to any skill's SKILL.md:
143
+
144
+ ```markdown
145
+ ## Auto-Trigger (After Completion)
146
+
147
+ When this skill completes, automatically trigger:
148
+
149
+ ```yaml
150
+ hooks:
151
+ after_complete:
152
+ - trigger: skill-name
153
+ mode: auto|background|ask_first
154
+ context: "relevant context"
155
+ on_error:
156
+ - trigger: self-improving-agent
157
+ mode: background
158
+ ```
159
+
160
+ ### Current Skill Hooks
161
+
162
+ - **prd-planner**: After PRD complete → self-improving-agent + session-logger
163
+ - **self-improving-agent**: After improvement → create-pr + session-logger
164
+ - **prd-implementation-precheck**: After implementation → self-improving-agent + session-logger
165
+ - **code-reviewer**: After review → self-improving-agent + session-logger
166
+ - **debugger**: After debugging → self-improving-agent + session-logger
167
+ - **create-pr**: After PR created → session-logger
168
+ - **session-logger**: No trigger (terminates chain)
169
+
170
+ ### Universal Learning Pattern
171
+
172
+ ```
173
+ ┌─────────────────────────────────────────────────────────────┐
174
+ │ ANY Skill Completes │
175
+ └──────────────┬──────────────────────────────────────────────┘
176
+
177
+
178
+ ┌──────────────────────┐
179
+ │ workflow-orchestrator │
180
+ └──────────┬───────────┘
181
+
182
+ ┌──────────┴─────────┐
183
+ ↓ ↓
184
+ self-improving-agent session-logger
185
+ ↓ ↓
186
+ Learn from experience Save context
187
+ ↓ ↓
188
+ Update skills Log session
189
+
190
+ create-pr (if modified)
191
+ ```
192
+ ```
193
+
194
+ ## Workflow Examples
195
+
196
+ ### Example 1: PRD Creation Workflow
197
+
198
+ ```
199
+ User: "Create a PRD for user authentication"
200
+
201
+ prd-planner executes
202
+
203
+ Phase 6 complete: PRD delivered
204
+
205
+ workflow-orchestrator detects milestone
206
+
207
+ ┌─────────────────────────────────┐
208
+ │ Background: self-improving-agent │ → Learns from PRD patterns
209
+ │ Auto: session-logger │ → Saves session
210
+ └─────────────────────────────────┘
211
+ ```
212
+
213
+ ### Example 2: Full Feature Workflow
214
+
215
+ ```
216
+ User: "Create a PRD and implement it"
217
+
218
+ prd-planner → workflow-orchestrator
219
+
220
+ self-improving-agent → workflow-orchestrator
221
+
222
+ prd-implementation-precheck
223
+
224
+ implementation complete → workflow-orchestrator
225
+
226
+ code-reviewer → self-improving-agent → workflow-orchestrator
227
+
228
+ create-pr → workflow-orchestrator
229
+
230
+ session-logger
231
+ ```
232
+
233
+ Each step triggers `self-improving-agent` to learn from the experience.
234
+
235
+ ## Implementation Steps
236
+
237
+ ### Step 1: Detect Milestone
238
+
239
+ Check for completion indicators:
240
+
241
+ ```bash
242
+ # PRD complete?
243
+ grep -q "COMPLETE" docs/{scope}-prd-task-plan.md
244
+
245
+ # All phases checked?
246
+ grep -q "^\- \[x\].*Phase 6" docs/{scope}-prd-task-plan.md
247
+
248
+ # PRD file exists?
249
+ ls docs/{scope}-prd.md
250
+ ```
251
+
252
+ ### Step 2: Read Trigger Config
253
+
254
+ ```bash
255
+ # Read hooks from auto-trigger skill
256
+ cat skills/auto-trigger/SKILL.md
257
+ ```
258
+
259
+ ### Step 3: Execute Hooks
260
+
261
+ For each hook in order (before_start, after_complete, on_error):
262
+ 1. Check if condition is met
263
+ 2. Execute based on mode
264
+ 3. Pass context to triggered skill
265
+ 4. Wait/continue based on mode
266
+
267
+ ### Step 4: Update Status
268
+
269
+ Log what was triggered and the result:
270
+
271
+ ```markdown
272
+ ## Workflow Execution
273
+
274
+ - [x] self-improving-agent (background) - Started
275
+ - [x] session-logger (auto) - Session saved
276
+ - [ ] create-pr (ask_first) - Pending user approval
277
+ ```
278
+
279
+ ## Skills with Auto-Trigger
280
+
281
+ | Skill | Triggers After |
282
+ |-------|----------------|
283
+ | `prd-planner` | self-improving-agent, session-logger |
284
+ | `self-improving-agent` | create-pr, session-logger |
285
+ | `prd-implementation-precheck` | code-reviewer, session-logger |
286
+ | `code-reviewer` | self-improving-agent, session-logger |
287
+ | `create-pr` | session-logger |
288
+ | `refactoring-specialist` | self-improving-agent, session-logger |
289
+ | `debugger` | self-improving-agent, session-logger |
290
+
291
+ ## Adding Auto-Trigger to Existing Skills
292
+
293
+ To add auto-trigger capability to an existing skill, add to the end of its SKILL.md:
294
+
295
+ ```markdown
296
+ ---
297
+
298
+ ## Auto-Trigger
299
+
300
+ When this skill completes, automatically trigger:
301
+
302
+ ```yaml
303
+ hooks:
304
+ after_complete:
305
+ - trigger: session-logger
306
+ mode: auto
307
+ context: "Save session context"
308
+ ```
309
+ ```
310
+
311
+ For more complex triggers, specify mode and context:
312
+
313
+ ```markdown
314
+ ## Auto-Trigger
315
+
316
+ When this skill completes:
317
+
318
+ ```yaml
319
+ hooks:
320
+ after_complete:
321
+ - trigger: next-skill
322
+ mode: background
323
+ context: "Description"
324
+ - trigger: session-logger
325
+ mode: auto
326
+ context: "Save session"
327
+ - trigger: create-pr
328
+ mode: ask_first
329
+ context: "Create PR if files modified"
330
+ on_error:
331
+ - trigger: self-improving-agent
332
+ mode: background
333
+ ```
334
+ ```
335
+
336
+ ## Best Practices
337
+
338
+ 1. **Always log to session** - Every workflow should end with session-logger
339
+ 2. **Ask before major actions** - PRs, deployments, destructive changes
340
+ 3. **Background for analysis** - Reflection, evaluation, optimization
341
+ 4. **Auto for status** - Logging, status updates, bookmarks
342
+ 5. **Don't create loops** - Ensure chains terminate
package/src/cli.js CHANGED
@@ -23,13 +23,13 @@ function main(argv, context) {
23
23
  case "init":
24
24
  return handleInit(options, context);
25
25
  case "status":
26
- return handleStatus(options);
26
+ return handleStatus(options, context);
27
27
  case "doctor":
28
- return handleDoctor(options);
28
+ return handleDoctor(options, context);
29
29
  case "repair":
30
30
  return handleRepair({ ...options, repair: true }, context);
31
31
  case "uninstall":
32
- return handleUninstall(options);
32
+ return handleUninstall(options, context);
33
33
  case "session-log":
34
34
  return handleSessionLog(options);
35
35
  case "self-improve":
@@ -167,15 +167,15 @@ function handleInit(options, context) {
167
167
  return Promise.resolve();
168
168
  }
169
169
 
170
- function handleStatus(options) {
171
- const settings = resolveSettings(options, {});
170
+ function handleStatus(options, context) {
171
+ const settings = resolveSettings(options, context || {});
172
172
  const status = collectStatus(settings);
173
173
  printStatus(status);
174
174
  return Promise.resolve();
175
175
  }
176
176
 
177
- function handleDoctor(options) {
178
- const settings = resolveSettings(options, {});
177
+ function handleDoctor(options, context) {
178
+ const settings = resolveSettings(options, context || {});
179
179
  const status = collectStatus(settings);
180
180
  const issues = summarizeIssues(status);
181
181
 
@@ -191,8 +191,8 @@ function handleDoctor(options) {
191
191
  return Promise.resolve();
192
192
  }
193
193
 
194
- function handleUninstall(options) {
195
- const settings = resolveSettings(options, {});
194
+ function handleUninstall(options, context) {
195
+ const settings = resolveSettings(options, context || {});
196
196
  const manifestPath = path.join(settings.claudeSkillsDir, ".agent-playbook.json");
197
197
  const manifest = readJsonSafe(manifestPath);
198
198
 
@@ -267,7 +267,9 @@ async function handleSelfImprove(options) {
267
267
  function resolveSettings(options, context) {
268
268
  const cwd = process.cwd();
269
269
  const repoRoot = options.repo ? path.resolve(options.repo) : findRepoRoot(cwd);
270
- const skillsSource = findSkillsSource(repoRoot || cwd);
270
+ const cliRoot =
271
+ context && context.cliPath ? path.resolve(path.dirname(context.cliPath), "..") : null;
272
+ const skillsSource = resolveSkillsSource([repoRoot || cwd, cliRoot]);
271
273
  const projectMode = Boolean(options.project);
272
274
 
273
275
  const envClaudeDir = process.env.AGENT_PLAYBOOK_CLAUDE_DIR;
@@ -324,6 +326,19 @@ function findSkillsSource(startDir) {
324
326
  return null;
325
327
  }
326
328
 
329
+ function resolveSkillsSource(candidates) {
330
+ for (const candidate of candidates) {
331
+ if (!candidate) {
332
+ continue;
333
+ }
334
+ const found = findSkillsSource(candidate);
335
+ if (found) {
336
+ return found;
337
+ }
338
+ }
339
+ return null;
340
+ }
341
+
327
342
  function linkSkills(sourceDir, targetDir, options) {
328
343
  const created = [];
329
344
  const skipped = [];