opencode-skills-collection 3.1.7 → 3.1.9
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/bundled-skills/.antigravity-install-manifest.json +10 -1
- package/bundled-skills/ai-loop/SKILL.md +136 -0
- package/bundled-skills/arrowspace/SKILL.md +116 -0
- package/bundled-skills/cron-doctor/SKILL.md +244 -0
- package/bundled-skills/cron-doctor/scripts/cli.js +75 -0
- package/bundled-skills/cron-doctor/scripts/cron-engine.js +638 -0
- package/bundled-skills/docs/contributors/quality-bar.md +1 -0
- package/bundled-skills/docs/contributors/skill-anatomy.md +19 -3
- package/bundled-skills/docs/integrations/jetski-cortex.md +3 -3
- package/bundled-skills/docs/integrations/jetski-gemini-loader/README.md +1 -1
- package/bundled-skills/docs/maintainers/categorization-implementation.md +14 -24
- package/bundled-skills/docs/maintainers/repo-growth-seo.md +3 -3
- package/bundled-skills/docs/maintainers/skills-update-guide.md +1 -1
- package/bundled-skills/docs/maintainers/smart-auto-categorization.md +24 -25
- package/bundled-skills/docs/users/bundles.md +1 -1
- package/bundled-skills/docs/users/claude-code-skills.md +1 -1
- package/bundled-skills/docs/users/faq.md +5 -5
- package/bundled-skills/docs/users/gemini-cli-skills.md +1 -1
- package/bundled-skills/docs/users/getting-started.md +1 -1
- package/bundled-skills/docs/users/kiro-integration.md +1 -1
- package/bundled-skills/docs/users/local-config.md +11 -11
- package/bundled-skills/docs/users/specialized-plugin-roadmap.md +3 -3
- package/bundled-skills/docs/users/usage.md +4 -4
- package/bundled-skills/docs/users/visual-guide.md +4 -4
- package/bundled-skills/docs/vietnamese/BUNDLES.vi.md +1 -1
- package/bundled-skills/docs/vietnamese/CONTRIBUTING.vi.md +15 -9
- package/bundled-skills/docs/vietnamese/FAQ.vi.md +30 -20
- package/bundled-skills/docs/vietnamese/GETTING_STARTED.vi.md +22 -14
- package/bundled-skills/docs/vietnamese/QUALITY_BAR.vi.md +9 -4
- package/bundled-skills/docs/vietnamese/README.vi.md +29 -30
- package/bundled-skills/docs/vietnamese/SKILLS_README.vi.md +3 -3
- package/bundled-skills/docs/vietnamese/SKILL_ANATOMY.vi.md +33 -5
- package/bundled-skills/docs/vietnamese/TRANSLATION_PLAN.vi.md +1 -1
- package/bundled-skills/docs/vietnamese/VISUAL_GUIDE.vi.md +17 -18
- package/bundled-skills/gh-image/SKILL.md +122 -0
- package/bundled-skills/github-actions-debugger/SKILL.md +99 -0
- package/bundled-skills/loki-mode/examples/todo-app-generated/frontend/package-lock.json +9 -9
- package/bundled-skills/loki-mode/examples/todo-app-generated/frontend/package.json +2 -2
- package/bundled-skills/premium-3d-website/SKILL.md +133 -0
- package/bundled-skills/sql-sentinel/SKILL.md +131 -0
- package/bundled-skills/web-project-brainstorming/SKILL.md +149 -0
- package/package.json +1 -1
- package/skills_index.json +176 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"updatedAt": "2026-06-
|
|
3
|
+
"updatedAt": "2026-06-28T02:10:47.668Z",
|
|
4
4
|
"entries": [
|
|
5
5
|
"00-andruia-consultant",
|
|
6
6
|
"007",
|
|
@@ -57,6 +57,7 @@
|
|
|
57
57
|
"ai-dev-jobs-mcp",
|
|
58
58
|
"ai-engineer",
|
|
59
59
|
"ai-engineering-toolkit",
|
|
60
|
+
"ai-loop",
|
|
60
61
|
"ai-md",
|
|
61
62
|
"ai-ml",
|
|
62
63
|
"ai-native-cli",
|
|
@@ -128,6 +129,7 @@
|
|
|
128
129
|
"architecture-decision-records",
|
|
129
130
|
"architecture-patterns",
|
|
130
131
|
"arm-cortex-expert",
|
|
132
|
+
"arrowspace",
|
|
131
133
|
"article-illustrations",
|
|
132
134
|
"asana-automation",
|
|
133
135
|
"ask-matt",
|
|
@@ -456,6 +458,7 @@
|
|
|
456
458
|
"create-pr",
|
|
457
459
|
"cred-omega",
|
|
458
460
|
"crewai",
|
|
461
|
+
"cron-doctor",
|
|
459
462
|
"crossframe",
|
|
460
463
|
"crossframe-casebook",
|
|
461
464
|
"crossframe-critical",
|
|
@@ -740,6 +743,7 @@
|
|
|
740
743
|
"geminiignore-finops",
|
|
741
744
|
"geo-fundamentals",
|
|
742
745
|
"geoffrey-hinton",
|
|
746
|
+
"gh-image",
|
|
743
747
|
"gh-review-requests",
|
|
744
748
|
"gha-security-review",
|
|
745
749
|
"git-advanced-workflows",
|
|
@@ -751,6 +755,7 @@
|
|
|
751
755
|
"git-pushing",
|
|
752
756
|
"github",
|
|
753
757
|
"github-actions-advanced",
|
|
758
|
+
"github-actions-debugger",
|
|
754
759
|
"github-actions-templates",
|
|
755
760
|
"github-automation",
|
|
756
761
|
"github-issue-creator",
|
|
@@ -1182,6 +1187,7 @@
|
|
|
1182
1187
|
"pptx-official",
|
|
1183
1188
|
"pr-merge-champion",
|
|
1184
1189
|
"pr-writer",
|
|
1190
|
+
"premium-3d-website",
|
|
1185
1191
|
"price-psychology-strategist",
|
|
1186
1192
|
"pricing-strategy",
|
|
1187
1193
|
"prisma-expert",
|
|
@@ -1426,6 +1432,7 @@
|
|
|
1426
1432
|
"sql-injection-testing",
|
|
1427
1433
|
"sql-optimization-patterns",
|
|
1428
1434
|
"sql-pro",
|
|
1435
|
+
"sql-sentinel",
|
|
1429
1436
|
"sqlmap-database-pentesting",
|
|
1430
1437
|
"square-automation",
|
|
1431
1438
|
"squirrel",
|
|
@@ -1517,6 +1524,7 @@
|
|
|
1517
1524
|
"test-fixing",
|
|
1518
1525
|
"testing-patterns",
|
|
1519
1526
|
"testing-qa",
|
|
1527
|
+
"the-honoured-one",
|
|
1520
1528
|
"theme-factory",
|
|
1521
1529
|
"threat-mitigation-mapping",
|
|
1522
1530
|
"threat-modeling-expert",
|
|
@@ -1626,6 +1634,7 @@
|
|
|
1626
1634
|
"web-design-guidelines",
|
|
1627
1635
|
"web-media-getter",
|
|
1628
1636
|
"web-performance-optimization",
|
|
1637
|
+
"web-project-brainstorming",
|
|
1629
1638
|
"web-scraper",
|
|
1630
1639
|
"web-security-testing",
|
|
1631
1640
|
"web3-testing",
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ai-loop
|
|
3
|
+
description: Runs a bounded spec-build-review development loop with explicit scope, stop conditions, and human approval gates for risky or ambiguous work.
|
|
4
|
+
category: workflow
|
|
5
|
+
risk: safe
|
|
6
|
+
source: community
|
|
7
|
+
date_added: "2026-06-27"
|
|
8
|
+
tags: [agent-workflow, specification, implementation, review, verification, feedback-loop]
|
|
9
|
+
tools: [claude, cursor, codex, gemini]
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# AI-Loop Skill
|
|
13
|
+
|
|
14
|
+
## Overview
|
|
15
|
+
|
|
16
|
+
The `ai-loop` skill structures a bounded development cycle for agentic workflows. By dividing the process into distinct planning (Spec), implementation (Build), and validation (Review) phases, it helps an agent build and correct scoped code changes while keeping requirements, risk gates, and stop conditions explicit.
|
|
17
|
+
|
|
18
|
+
## When to Use This Skill
|
|
19
|
+
|
|
20
|
+
- Use when you need a feature built from scratch or heavily modified, and you want the agent to handle the lifecycle (specification, implementation, and verification) inside one clearly bounded workflow.
|
|
21
|
+
- Use when working with isolated components, modules, or features that have well-defined scopes and constraints.
|
|
22
|
+
- Use when the user asks for a complete development pass but the work still has clear success criteria, a reasonable verification path, and no unresolved safety or product decisions.
|
|
23
|
+
|
|
24
|
+
## How It Works
|
|
25
|
+
|
|
26
|
+
This skill executes a controlled development loop composed of three phases: Spec, Build, and Review. When invoked, the agent moves through those phases until the scoped requirements pass verification, a stop condition is reached, or human approval is needed.
|
|
27
|
+
|
|
28
|
+
Before starting, define:
|
|
29
|
+
|
|
30
|
+
- The maximum number of build-review iterations.
|
|
31
|
+
- The verification commands or manual checks that count as evidence.
|
|
32
|
+
- The actions that require explicit approval, such as destructive commands, production changes, external service writes, or broad architectural pivots.
|
|
33
|
+
|
|
34
|
+
### Phase 1: Spec (Planning)
|
|
35
|
+
|
|
36
|
+
1. Interview the user about the feature or app they want to build. Ask one focused question at a time until you fully understand the goal, the must-have requirements, the constraints, and what "done" looks like.
|
|
37
|
+
2. **Do not start building yet.**
|
|
38
|
+
3. When you have enough information, write a clear, detailed specification and save it to `specs/<feature-name>.md`.
|
|
39
|
+
4. The spec must include:
|
|
40
|
+
- The objective
|
|
41
|
+
- The exact requirements
|
|
42
|
+
- Edge cases to handle
|
|
43
|
+
- A concrete definition of done that someone could check the build against
|
|
44
|
+
- The iteration budget, verification commands, and approval gates.
|
|
45
|
+
|
|
46
|
+
### Phase 2: Build (Implementation)
|
|
47
|
+
|
|
48
|
+
1. Read the spec you just created in `specs/<feature-name>.md`.
|
|
49
|
+
2. Build exactly what it describes.
|
|
50
|
+
3. **Do not add features**, do not refactor unrelated code, and do not invent requirements that aren't in the spec.
|
|
51
|
+
4. Focus strictly on fulfilling the spec. List which spec requirements you covered so the review step can check them.
|
|
52
|
+
|
|
53
|
+
### Phase 3: Review (Verification)
|
|
54
|
+
|
|
55
|
+
1. Compare your implementation against `specs/<feature-name>.md`.
|
|
56
|
+
2. Go requirement by requirement and verify if it was met. List every gap, bug, or missing piece, naming the exact spec item each one fails.
|
|
57
|
+
3. If anything fails and the iteration budget is not exhausted, write the specific fixes needed and **loop back to Phase 2 (Build)** to address them.
|
|
58
|
+
4. Stop and ask for human input when the next fix would change the spec, exceed the iteration budget, require risky operations, or depend on product decisions not captured in the spec.
|
|
59
|
+
5. Only pass the build and conclude the skill execution when every requirement in the spec is fully met and the declared verification evidence has passed.
|
|
60
|
+
|
|
61
|
+
## Examples
|
|
62
|
+
|
|
63
|
+
### Example 1: Creating a Basic Statistics Helper
|
|
64
|
+
|
|
65
|
+
**User:**
|
|
66
|
+
> I want to add a utility for calculating basic statistics (mean, median, mode) of an array of numbers.
|
|
67
|
+
|
|
68
|
+
**Agent (Phase 1 - Spec):**
|
|
69
|
+
> I can help with that. To get started, what programming language should this statistics calculator be implemented in? Also, how should empty arrays or invalid inputs be handled?
|
|
70
|
+
|
|
71
|
+
**User:**
|
|
72
|
+
> JavaScript. If the array is empty, return null. If there are non-numbers, ignore them.
|
|
73
|
+
|
|
74
|
+
**Agent (Phase 1 - Spec):**
|
|
75
|
+
> Thank you. I have created the specification file at `specs/stats-calculator.md` with the requirements we discussed. Now, I will start implementing it.
|
|
76
|
+
|
|
77
|
+
**Agent (Phase 2 - Build):**
|
|
78
|
+
> *(Creates `stats_calculator.js` and implements `mean`, `median`, and `mode` matching the spec exactly)*
|
|
79
|
+
> I have finished implementing the calculator. I will now verify the implementation.
|
|
80
|
+
|
|
81
|
+
**Agent (Phase 3 - Review):**
|
|
82
|
+
> Checking implementation against `specs/stats-calculator.md`:
|
|
83
|
+
> - Requirement: mean calculation -> PASS
|
|
84
|
+
> - Requirement: median calculation -> PASS
|
|
85
|
+
> - Requirement: mode calculation -> PASS
|
|
86
|
+
> - Requirement: empty array returns null -> PASS
|
|
87
|
+
> - Requirement: non-numbers are ignored -> FAIL (I noticed `mode` doesn't filter out non-numbers).
|
|
88
|
+
>
|
|
89
|
+
> I will now loop back to Phase 2 to fix the `mode` function.
|
|
90
|
+
|
|
91
|
+
**Agent (Phase 2 - Build Loop-Back):**
|
|
92
|
+
> *(Fixes `mode` to filter out non-numbers)*
|
|
93
|
+
> I have updated the implementation. Let's re-verify.
|
|
94
|
+
|
|
95
|
+
**Agent (Phase 3 - Review):**
|
|
96
|
+
> - Requirement: mode filters non-numbers -> PASS
|
|
97
|
+
>
|
|
98
|
+
> All requirements passed! The statistics calculator is complete and verified.
|
|
99
|
+
|
|
100
|
+
## Best Practices
|
|
101
|
+
|
|
102
|
+
- ✅ Do ask clarifying questions one at a time to avoid overwhelming the user during the planning phase.
|
|
103
|
+
- ✅ Do document edge cases explicitly in `specs/<feature-name>.md` before writing any code.
|
|
104
|
+
- ✅ Do stick strictly to the approved specification during the build phase.
|
|
105
|
+
- ✅ Do cap the loop with a small iteration budget and report exactly what remains if the budget is exhausted.
|
|
106
|
+
- ✅ Do pause for explicit approval before destructive, production, credentialed, or externally visible actions.
|
|
107
|
+
- ❌ Don't implement extra features or perform unrelated refactorings that aren't specified.
|
|
108
|
+
- ❌ Don't skip the review phase or pass it without verifying every single requirement.
|
|
109
|
+
- ❌ Don't keep retrying the same failing fix without new evidence or a changed approach.
|
|
110
|
+
|
|
111
|
+
## Limitations
|
|
112
|
+
|
|
113
|
+
- This skill requires sufficient context about the feature to be provided during the Spec phase.
|
|
114
|
+
- It is best suited for isolated features or tasks with clear boundaries, rather than open-ended architectural refactoring.
|
|
115
|
+
- The review phase relies on the agent's self-assessment against the generated spec; manual review is still recommended for critical systems.
|
|
116
|
+
- It is not a replacement for human approval on security-sensitive, destructive, production, compliance, or externally visible changes.
|
|
117
|
+
- It should stop rather than continue if requirements conflict, tests cannot run, or verification depends on unavailable credentials or systems.
|
|
118
|
+
|
|
119
|
+
## Security & Safety Notes
|
|
120
|
+
|
|
121
|
+
- Be cautious when running or testing code generated during the Build phase. Always run tests in a safe, sandboxed environment.
|
|
122
|
+
- Avoid executing arbitrary shell commands provided directly by the user without validating their safety.
|
|
123
|
+
- Make sure no hardcoded secrets, keys, or credentials are added to the code or specifications.
|
|
124
|
+
- Treat production deploys, data migrations, payment flows, credential changes, and external write actions as approval-gated work.
|
|
125
|
+
|
|
126
|
+
## Common Pitfalls
|
|
127
|
+
|
|
128
|
+
- **Problem:** The agent tries to build a huge system all at once, leading to an overcomplicated spec and incomplete implementation.
|
|
129
|
+
**Solution:** Keep the scope of `ai-loop` to small, modular features. Break larger systems into multiple independent loops.
|
|
130
|
+
- **Problem:** The spec is vague, causing the build phase to rely on assumptions.
|
|
131
|
+
**Solution:** Spend extra time in the planning phase asking targeted questions to pin down requirements.
|
|
132
|
+
|
|
133
|
+
## Related Skills
|
|
134
|
+
|
|
135
|
+
- `@plan-writing` - For writing more detailed implementation plans for larger projects.
|
|
136
|
+
- `@ask-questions-if-underspecified` - For standard guidelines on interviewing the user.
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: arrowspace
|
|
3
|
+
description: "Spectral vector search using graph Laplacian eigenstructure. Use when cosine/L2 similarity misses latent structure in your embeddings."
|
|
4
|
+
category: data
|
|
5
|
+
risk: safe
|
|
6
|
+
source: community
|
|
7
|
+
source_repo: Genefold/arrowspace-skills
|
|
8
|
+
source_type: community
|
|
9
|
+
date_added: "2026-06-25"
|
|
10
|
+
author: Genefold AI
|
|
11
|
+
license: Apache-2.0
|
|
12
|
+
license_source: "https://github.com/Genefold/arrowspace-skills/blob/main/LICENSE"
|
|
13
|
+
tags: [vector-search, spectral-analysis, graph-laplacian, embeddings, lambda-tau]
|
|
14
|
+
tools: [claude, cursor, codex, gemini, opencode]
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
# ArrowSpace
|
|
18
|
+
|
|
19
|
+
Spectral vector search that augments nearest-neighbour search with graph Laplacian features. Computes a Laplacian over the item graph and uses the Rayleigh quotient to produce a λτ (lambda-tau) score per item, enabling search that respects both semantic similarity and structural role.
|
|
20
|
+
|
|
21
|
+
## When to Use This Skill
|
|
22
|
+
|
|
23
|
+
- Cosine or L2 similarity misses latent structure in your embeddings
|
|
24
|
+
- You want graph-based retrieval with spectral awareness
|
|
25
|
+
- You need to characterise the spectral properties of an embedding space
|
|
26
|
+
- You are building RAG pipelines where contextual role matters alongside semantic content
|
|
27
|
+
|
|
28
|
+
## How It Works
|
|
29
|
+
|
|
30
|
+
### Step 1: Install and import
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
pip install arrowspace
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
```python
|
|
37
|
+
from arrowspace import ArrowSpaceBuilder
|
|
38
|
+
import numpy as np
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Step 2: Prepare your data
|
|
42
|
+
|
|
43
|
+
Pass an (N, d) float64 NumPy array of embedding vectors:
|
|
44
|
+
|
|
45
|
+
```python
|
|
46
|
+
items = np.array([[0.1, 0.2, 0.3],
|
|
47
|
+
[0.0, 0.5, 0.1],
|
|
48
|
+
[0.9, 0.1, 0.0]], dtype=np.float64)
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Step 3: Configure graph parameters
|
|
52
|
+
|
|
53
|
+
```python
|
|
54
|
+
graph_params = {"eps": 0.2, "k": 6, "topk": 3, "p": 2.0, "sigma": 1.0}
|
|
55
|
+
builder = ArrowSpaceBuilder(items, graph_params=graph_params)
|
|
56
|
+
aspace = builder.build()
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Step 4: Query
|
|
60
|
+
|
|
61
|
+
```python
|
|
62
|
+
lambdas = aspace.lambdas() # array indexed by insertion order
|
|
63
|
+
sorted_res = aspace.lambdas_sorted() # (score, index) pairs ascending
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Higher λτ values indicate items that are both semantically close and structurally central.
|
|
67
|
+
|
|
68
|
+
## Examples
|
|
69
|
+
|
|
70
|
+
### Example 1: Basic spectral retrieval
|
|
71
|
+
|
|
72
|
+
```python
|
|
73
|
+
items = np.random.randn(100, 64).astype(np.float64)
|
|
74
|
+
builder = ArrowSpaceBuilder(items, graph_params={"eps": 0.5, "k": 10, "topk": 5, "p": 2.0, "sigma": None})
|
|
75
|
+
aspace = builder.build()
|
|
76
|
+
scores = aspace.lambdas()
|
|
77
|
+
top_indices = np.argsort(scores)[-5:]
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Example 2: Compare spectral vs cosine ranking
|
|
81
|
+
|
|
82
|
+
```python
|
|
83
|
+
from sklearn.metrics.pairwise import cosine_similarity
|
|
84
|
+
cos_sim = cosine_similarity(items)
|
|
85
|
+
cosine_order = np.argsort(cos_sim[0])[::-1]
|
|
86
|
+
spectral_order = np.argsort(aspace.lambdas())[::-1]
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Best Practices
|
|
90
|
+
|
|
91
|
+
- ✅ Normalise embeddings to unit norm before passing to ArrowSpace
|
|
92
|
+
- ✅ Start with eps proportional to 1/sqrt(dim) and tune from there
|
|
93
|
+
- ✅ Use k between 3 and 25 depending on dataset size (rule: N/50)
|
|
94
|
+
- ✅ Set sigma=None to auto-select kernel width from distance distribution
|
|
95
|
+
- ❌ Don't use with fewer than 10 items (graph structure is not meaningful)
|
|
96
|
+
- ❌ Don't use for real-time streaming data (ArrowSpace is batch-oriented)
|
|
97
|
+
|
|
98
|
+
## Limitations
|
|
99
|
+
|
|
100
|
+
- This skill does not replace environment-specific validation, testing, or expert review.
|
|
101
|
+
- ArrowSpace is batch-oriented and not designed for real-time indexing of streaming data.
|
|
102
|
+
|
|
103
|
+
## Common Pitfalls
|
|
104
|
+
|
|
105
|
+
- **Problem:** eps is too small, producing a disconnected graph
|
|
106
|
+
**Solution:** Increase eps, or set it proportional to 1/sqrt(embedding_dim)
|
|
107
|
+
|
|
108
|
+
- **Problem:** k is too large, producing a dense graph with washed-out spectral features
|
|
109
|
+
**Solution:** Keep k ≤ 25 for most datasets
|
|
110
|
+
|
|
111
|
+
## Related Skills
|
|
112
|
+
|
|
113
|
+
- `vector-database-engineer` — General vector database expertise
|
|
114
|
+
- `embedding-strategies` — Embedding model selection and chunking
|
|
115
|
+
- `similarity-search-patterns` — Semantic search implementation patterns
|
|
116
|
+
- `hybrid-search-implementation` — Combined semantic + keyword search
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: cron-doctor
|
|
3
|
+
description: "Diagnose and validate cron expressions before they ship. Catches the five silent death-traps: impossible dates that never fire, OR-semantics that fire too often, midnight spikes, uneven step drift, and leap-year February 29."
|
|
4
|
+
category: devops
|
|
5
|
+
risk: safe
|
|
6
|
+
source: community
|
|
7
|
+
source_repo: takeaseatventure/devops-skills
|
|
8
|
+
source_type: community
|
|
9
|
+
date_added: "2026-06-26"
|
|
10
|
+
author: takeaseat
|
|
11
|
+
tags: [cron, crontab, scheduling, devops, debugging, kubernetes, validation]
|
|
12
|
+
tools: [claude, cursor, codex, gemini, opencode]
|
|
13
|
+
license: "MIT"
|
|
14
|
+
license_source: "https://github.com/takeaseatventure/devops-skills/blob/main/LICENSE"
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
# cron-doctor
|
|
18
|
+
|
|
19
|
+
## Overview
|
|
20
|
+
|
|
21
|
+
Cron is deceptively error-prone. The failure mode is **silent** — a syntactically
|
|
22
|
+
valid expression that simply never fires, or fires far more often than intended.
|
|
23
|
+
`0 0 30 2 *` parses cleanly and then sits dead forever (February has no 30th).
|
|
24
|
+
`0 0 1,15 * 1` looks like "1st and 15th if Monday" but actually means "1st, 15th,
|
|
25
|
+
**OR** every Monday" — ~6 fires/month instead of ~2.
|
|
26
|
+
|
|
27
|
+
This skill teaches an agent to catch those before they reach production. It comes
|
|
28
|
+
with a zero-dependency validation engine (`scripts/cron-engine.js`, no install
|
|
29
|
+
needed) that parses, describes, deep-validates, and computes next fire times.
|
|
30
|
+
|
|
31
|
+
## When to Use This Skill
|
|
32
|
+
|
|
33
|
+
- Use when a user writes, edits, reviews, or deploys a cron expression — in a
|
|
34
|
+
crontab, a Kubernetes `CronJob`, a GitHub Actions `schedule`, an Airflow DAG,
|
|
35
|
+
a Celery beat schedule, a systemd timer, or any scheduled task.
|
|
36
|
+
- Use when debugging a job that "didn't fire" or "fired at the wrong time."
|
|
37
|
+
- Use when a user asks "what does this cron expression mean?" or "when will this
|
|
38
|
+
run next?" or "how often does this run per year?"
|
|
39
|
+
- Use when reviewing a CI/CD pipeline or infrastructure config that contains a
|
|
40
|
+
`schedule` field.
|
|
41
|
+
- Use when a user pastes a 5-field cron expression and asks for a sanity check.
|
|
42
|
+
|
|
43
|
+
## How It Works
|
|
44
|
+
|
|
45
|
+
### Step 1: Parse the expression
|
|
46
|
+
|
|
47
|
+
Split on whitespace into 5 fields: minute, hour, day-of-month, month, day-of-week.
|
|
48
|
+
Confirm valid ranges:
|
|
49
|
+
|
|
50
|
+
| Field | Position | Range | Notes |
|
|
51
|
+
|-------|----------|-------|-------|
|
|
52
|
+
| minute | 1 | 0–59 | |
|
|
53
|
+
| hour | 2 | 0–23 | |
|
|
54
|
+
| day-of-month | 3 | 1–31 | |
|
|
55
|
+
| month | 4 | 1–12 | names (JAN–DEC) accepted |
|
|
56
|
+
| day-of-week | 5 | 0–7 | 0 and 7 both = Sunday; names (SUN–SAT) accepted |
|
|
57
|
+
|
|
58
|
+
### Step 2: Describe it in plain English
|
|
59
|
+
|
|
60
|
+
State what the user *thinks* it does vs. what it *actually* does. Be explicit
|
|
61
|
+
about OR-vs-AND semantics for day-of-month + day-of-week (see death-trap #2).
|
|
62
|
+
|
|
63
|
+
### Step 3: Run the trap checklist
|
|
64
|
+
|
|
65
|
+
Check the five death-traps below and flag any that apply.
|
|
66
|
+
|
|
67
|
+
### Step 4: Calculate next runs and annual fire count
|
|
68
|
+
|
|
69
|
+
Compute the next 5 fire times as concrete dates so the user can verify the
|
|
70
|
+
schedule behaves as expected. Estimate annual fire count — a schedule that fires
|
|
71
|
+
365×/year vs. 12×/year is a ~30× cost and load difference.
|
|
72
|
+
|
|
73
|
+
## The Five Cron Death-Traps
|
|
74
|
+
|
|
75
|
+
These are the bugs that pass `crontab -l` validation but break in production.
|
|
76
|
+
|
|
77
|
+
### 1. Impossible dates — the "never fires" bug
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
0 0 30 2 *
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
**Valid syntax. Never fires.** February has no 30th. This schedule is a dead job
|
|
84
|
+
that silently sits forever. The same applies to day 31 in any 30-day month:
|
|
85
|
+
`0 0 31 4 *`, `0 0 31 6 *`, `0 0 31 9 *`, `0 0 31 11 *`.
|
|
86
|
+
|
|
87
|
+
**Fix:** use `0 0 28-31 * *` and check for end-of-month in the script, or use `L`
|
|
88
|
+
(last day) syntax if your scheduler supports it.
|
|
89
|
+
|
|
90
|
+
### 2. OR-semantics — the "fires too often" bug
|
|
91
|
+
|
|
92
|
+
```
|
|
93
|
+
0 0 1,15 * 1
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
**Does NOT mean** "midnight on the 1st and 15th if it's Monday."
|
|
97
|
+
**Does mean** "midnight on the 1st, the 15th, **OR** every Monday." That's ~6
|
|
98
|
+
fires/month instead of ~2.
|
|
99
|
+
|
|
100
|
+
This is the single most misunderstood cron rule. When **both** day-of-month AND
|
|
101
|
+
day-of-week are restricted (neither is `*`), cron uses OR logic, not AND.
|
|
102
|
+
|
|
103
|
+
**Fix:** if you need "1st and 15th only if Monday," run daily and check in the
|
|
104
|
+
script:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
0 0 * * 1 [ "$(date +%d)" = "01" -o "$(date +%d)" = "15" ] && your-command
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### 3. Midnight spike — the "everything at once" bug
|
|
111
|
+
|
|
112
|
+
```
|
|
113
|
+
0 0 * * *
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Every job scheduled at `0 0` competes for resources at exactly 00:00. Database
|
|
117
|
+
backups, log rotations, cert renewals, report generation — all fire simultaneously.
|
|
118
|
+
This causes load spikes, connection-pool exhaustion, and cascading timeouts.
|
|
119
|
+
|
|
120
|
+
**Fix:** stagger jobs across the hour. Use `17 2 * * *` or `43 3 * * *` instead of
|
|
121
|
+
`0 0`. Jitter is your friend.
|
|
122
|
+
|
|
123
|
+
### 4. Uneven steps — the "drift" bug
|
|
124
|
+
|
|
125
|
+
```
|
|
126
|
+
*/7 * * * *
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
**Does NOT mean** "every 7 minutes evenly." It means "every 7 minutes starting at
|
|
130
|
+
0, then resets at 60." So: 0, 7, 14, 21, 28, 35, 42, 49, 56 — then 0 again
|
|
131
|
+
(a 4-minute gap). The intervals drift: 7,7,7,7,7,7,7,7,**4**.
|
|
132
|
+
|
|
133
|
+
**Fix:** 60 is not divisible by 7. Use step values that divide 60 evenly: `*/5`,
|
|
134
|
+
`*/10`, `*/15`, `*/20`, `*/30`. If you truly need every-7-minutes, use a loop with
|
|
135
|
+
`sleep 420`.
|
|
136
|
+
|
|
137
|
+
### 5. Leap-year February 29 — the "annual surprise"
|
|
138
|
+
|
|
139
|
+
```
|
|
140
|
+
0 0 29 2 *
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Fires only on leap years — February 29, 2024 / 2028 / 2032… If someone writes this
|
|
144
|
+
expecting "end of February," they'll be confused for 3 out of every 4 years.
|
|
145
|
+
|
|
146
|
+
**Fix:** use `0 0 28 2 *` and handle the 29th case in the script if needed.
|
|
147
|
+
|
|
148
|
+
## Using the validation script
|
|
149
|
+
|
|
150
|
+
This skill ships a zero-dependency engine at `scripts/cron-engine.js` (Node.js, no
|
|
151
|
+
`npm install` needed). You can use it programmatically or from the CLI:
|
|
152
|
+
|
|
153
|
+
```javascript
|
|
154
|
+
// Programmatic — Node.js, zero dependencies
|
|
155
|
+
const { describe, validate, nextRuns, formatNextRuns } = require('./scripts/cron-engine.js');
|
|
156
|
+
|
|
157
|
+
// Parse + describe -> returns { text, error, parsed }
|
|
158
|
+
const d = describe('0 0 30 2 *');
|
|
159
|
+
console.log(d.text); // "At 00:00, on day-of-month 30 in in FEB"
|
|
160
|
+
|
|
161
|
+
// Deep validation -> catches the traps
|
|
162
|
+
const result = validate('0 0 30 2 *');
|
|
163
|
+
console.log(result.valid); // true (syntax is valid)
|
|
164
|
+
console.log(result.observations); // includes the "never fires" insight
|
|
165
|
+
console.log(result.suggestions); // e.g. "Midnight is a common spike..."
|
|
166
|
+
|
|
167
|
+
// Next 5 fire times -> returns Date[]
|
|
168
|
+
const runs = nextRuns('0 9 * * 1-5', new Date(), 5);
|
|
169
|
+
console.log(formatNextRuns(runs, new Date())); // [{ date, relative, formatted }, ...]
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
# CLI (via the bundled wrapper)
|
|
174
|
+
node scripts/cli.js describe "*/5 * * * *"
|
|
175
|
+
node scripts/cli.js validate "0 0 30 2 *"
|
|
176
|
+
node scripts/cli.js next "0 9 * * 1-5" 5
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## Common cron presets
|
|
180
|
+
|
|
181
|
+
| Expression | Description | Use case |
|
|
182
|
+
|-----------|-------------|----------|
|
|
183
|
+
| `*/5 * * * *` | Every 5 minutes | Health checks, polling |
|
|
184
|
+
| `0 * * * *` | Every hour | Hourly aggregation |
|
|
185
|
+
| `0 */2 * * *` | Every 2 hours | Semi-frequent sync |
|
|
186
|
+
| `0 9 * * 1-5` | 9am Mon–Fri | Business-hours task |
|
|
187
|
+
| `0 2 * * *` | 2am daily | Off-peak batch (avoid midnight) |
|
|
188
|
+
| `0 0 * * 0` | Midnight Sunday | Weekly maintenance |
|
|
189
|
+
| `0 0 1 * *` | Midnight 1st of month | Monthly report |
|
|
190
|
+
| `0 0 1 1 *` | Midnight Jan 1st | Annual task |
|
|
191
|
+
|
|
192
|
+
## Best Practices
|
|
193
|
+
|
|
194
|
+
- ✅ Always provide the plain-English description AND run the trap checklist.
|
|
195
|
+
- ✅ Stagger midnight jobs to avoid the spike.
|
|
196
|
+
- ✅ Prefer step values that divide 60 evenly (`*/5`, `*/15`, `*/30`).
|
|
197
|
+
- ✅ Add a comment above every crontab line explaining intent.
|
|
198
|
+
- ✅ Set an explicit timezone (`CRON_TZ`) on schedulers that support it.
|
|
199
|
+
- ❌ Don't trust `crontab -l` validation — it only checks syntax, not semantics.
|
|
200
|
+
- ❌ Don't restrict both day-of-month and day-of-week without confirming OR-logic.
|
|
201
|
+
- ❌ Don't schedule everything at `0 0`.
|
|
202
|
+
|
|
203
|
+
## Common Pitfalls
|
|
204
|
+
|
|
205
|
+
- **Problem:** "My cron job isn't running."
|
|
206
|
+
**Solution:** Check for an impossible date (trap #1) and confirm the daemon is
|
|
207
|
+
running (`service cron status` / `systemctl status crond`). Verify the file
|
|
208
|
+
ends with a newline and has correct ownership.
|
|
209
|
+
|
|
210
|
+
- **Problem:** "My job runs far more often than expected."
|
|
211
|
+
**Solution:** You hit OR-semantics (trap #2). If both day-of-month and
|
|
212
|
+
day-of-week are set, cron ORs them. Move one to `*` or guard in-script.
|
|
213
|
+
|
|
214
|
+
- **Problem:** "Intervals are uneven — sometimes 7 min, sometimes 4."
|
|
215
|
+
**Solution:** Step value doesn't divide 60 evenly (trap #4). Use a divisor of 60.
|
|
216
|
+
|
|
217
|
+
- **Problem:** "My job works locally but not in the cluster."
|
|
218
|
+
**Solution:** Timezone mismatch. Kubernetes `CronJob` and GitHub Actions default
|
|
219
|
+
to UTC. Confirm `timeZone` / `TZ` is set as intended.
|
|
220
|
+
|
|
221
|
+
## Limitations
|
|
222
|
+
|
|
223
|
+
- This skill targets standard 5-field cron as implemented by Vixie cron, systemd
|
|
224
|
+
timers, Kubernetes `CronJob`, GitHub Actions `schedule`, and most libraries. It
|
|
225
|
+
does **not** validate Quartz 6/7-field expressions with seconds/years, nor
|
|
226
|
+
non-standard `@reboot` / `L` / `#` extensions without a note.
|
|
227
|
+
- Estimated annual fire counts assume a non-leap reference year; February 29
|
|
228
|
+
schedules (trap #5) are flagged explicitly.
|
|
229
|
+
- This skill does not replace environment-specific validation, testing, or expert
|
|
230
|
+
review. Stop and ask for clarification if required inputs, permissions, or
|
|
231
|
+
safety boundaries are missing.
|
|
232
|
+
|
|
233
|
+
## Related Skills
|
|
234
|
+
|
|
235
|
+
- `docker-expert` — when the cron job runs inside a container and the issue is the
|
|
236
|
+
container/entrypoint rather than the schedule.
|
|
237
|
+
- `kubernetes-deployment` — when validating a `CronJob` manifest's `spec.schedule`
|
|
238
|
+
field alongside the broader resource config.
|
|
239
|
+
|
|
240
|
+
## Security & Safety Notes
|
|
241
|
+
|
|
242
|
+
This skill is read-only and `risk: safe`. The validation script performs no file
|
|
243
|
+
writes, network calls, or mutations — it only parses and computes. It is safe to
|
|
244
|
+
run against any cron expression without preconditions.
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
// Minimal CLI wrapper for cron-engine.js. Zero dependencies.
|
|
5
|
+
// Usage:
|
|
6
|
+
// node cli.js describe "<cron>"
|
|
7
|
+
// node cli.js validate "<cron>"
|
|
8
|
+
// node cli.js next "<cron>" [count]
|
|
9
|
+
|
|
10
|
+
const cron = require('./cron-engine.js');
|
|
11
|
+
const expr = process.argv[3];
|
|
12
|
+
const cmd = process.argv[2];
|
|
13
|
+
|
|
14
|
+
if (!cmd || !expr) {
|
|
15
|
+
console.error('Usage: node cli.js <describe|validate|next> "<cron-expr>" [count]');
|
|
16
|
+
console.error('Examples:');
|
|
17
|
+
console.error(' node cli.js describe "*/5 * * * *"');
|
|
18
|
+
console.error(' node cli.js validate "0 0 30 2 *"');
|
|
19
|
+
console.error(' node cli.js next "0 9 * * 1-5" 5');
|
|
20
|
+
process.exit(2);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function safe(fn) {
|
|
24
|
+
try {
|
|
25
|
+
fn();
|
|
26
|
+
} catch (e) {
|
|
27
|
+
console.error('Error: ' + (e.message || e));
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
switch (cmd) {
|
|
33
|
+
case 'describe':
|
|
34
|
+
safe(() => {
|
|
35
|
+
const d = cron.describe(expr);
|
|
36
|
+
console.log(d.text || d.description || JSON.stringify(d));
|
|
37
|
+
});
|
|
38
|
+
break;
|
|
39
|
+
|
|
40
|
+
case 'validate':
|
|
41
|
+
safe(() => {
|
|
42
|
+
const r = cron.validate(expr);
|
|
43
|
+
console.log('valid: ' + r.valid);
|
|
44
|
+
if (r.description) console.log('description: ' + r.description);
|
|
45
|
+
if (r.warnings && r.warnings.length) {
|
|
46
|
+
console.log('warnings:');
|
|
47
|
+
r.warnings.forEach((w) => console.log(' - ' + w));
|
|
48
|
+
}
|
|
49
|
+
if (r.observations && r.observations.length) {
|
|
50
|
+
console.log('observations:');
|
|
51
|
+
r.observations.forEach((o) => console.log(' [' + (o.level || 'info') + '] ' + o.message));
|
|
52
|
+
}
|
|
53
|
+
if (r.suggestions && r.suggestions.length) {
|
|
54
|
+
console.log('suggestions:');
|
|
55
|
+
r.suggestions.forEach((s) => console.log(' [' + (s.level || 'info') + '] ' + s.message));
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
break;
|
|
59
|
+
|
|
60
|
+
case 'next':
|
|
61
|
+
safe(() => {
|
|
62
|
+
const count = parseInt(process.argv[4] || '5', 10);
|
|
63
|
+
const runs = cron.nextRuns(expr, new Date(), count);
|
|
64
|
+
const formatted = cron.formatNextRuns(runs, new Date());
|
|
65
|
+
formatted.forEach((f) =>
|
|
66
|
+
console.log(f.relative + '\t' + f.formatted + '\t' + f.date.toString())
|
|
67
|
+
);
|
|
68
|
+
});
|
|
69
|
+
break;
|
|
70
|
+
|
|
71
|
+
default:
|
|
72
|
+
console.error('Unknown command: ' + cmd);
|
|
73
|
+
console.error('Commands: describe, validate, next');
|
|
74
|
+
process.exit(2);
|
|
75
|
+
}
|