@wonsukchoi/crondex 0.5.0 → 0.7.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/README.md +9 -1
- package/bin/crondex.js +85 -0
- package/catalog.json +2397 -522
- package/jobs/construction/inspection-deadline-reminder.yaml +31 -0
- package/jobs/construction/permit-expiry-check.yaml +31 -0
- package/jobs/content/canonical-tag-check.yaml +25 -0
- package/jobs/content/hreflang-audit.yaml +25 -0
- package/jobs/content/image-alt-text-audit.yaml +21 -0
- package/jobs/content/page-speed-regression-watch.yaml +26 -0
- package/jobs/content/sitemap-freshness-check.yaml +31 -0
- package/jobs/content/stale-post-audit.yaml +28 -0
- package/jobs/creator/content-calendar-gap-check.yaml +31 -0
- package/jobs/creator/engagement-drop-watch.yaml +36 -0
- package/jobs/devops/cdn-cache-purge-reminder.yaml +27 -0
- package/jobs/devops/ci-build-time-regression-watch.yaml +35 -0
- package/jobs/devops/error-rate-spike-watch.yaml +43 -0
- package/jobs/devops/feature-flag-staleness-audit.yaml +30 -0
- package/jobs/devops/k8s-pod-restart-watch.yaml +26 -0
- package/jobs/devops/log-forwarding-health-check.yaml +32 -0
- package/jobs/devops/staging-prod-config-diff.yaml +32 -0
- package/jobs/devops/terraform-drift-check.yaml +24 -0
- package/jobs/education/assignment-grading-backlog-check.yaml +23 -0
- package/jobs/education/attendance-anomaly-check.yaml +33 -0
- package/jobs/events/rsvp-followup-reminder.yaml +30 -0
- package/jobs/events/vendor-payment-deadline-reminder.yaml +31 -0
- package/jobs/finance/budget-overspend-check.yaml +29 -0
- package/jobs/finance/fx-rate-watch.yaml +33 -0
- package/jobs/finance/payroll-run-reminder.yaml +27 -0
- package/jobs/finance/recurring-payment-failure-check.yaml +23 -0
- package/jobs/fleet/fuel-card-anomaly-check.yaml +37 -0
- package/jobs/fleet/vehicle-maintenance-due-check.yaml +36 -0
- package/jobs/growth/churn-risk-watch.yaml +33 -0
- package/jobs/growth/trial-expiring-nudge.yaml +33 -0
- package/jobs/hiring/candidate-followup-nudge.yaml +23 -0
- package/jobs/hiring/open-req-aging-check.yaml +31 -0
- package/jobs/home/car-maintenance-due-reminder.yaml +30 -0
- package/jobs/home/warranty-expiry-reminder.yaml +31 -0
- package/jobs/hospitality/food-safety-temp-log-check.yaml +36 -0
- package/jobs/hospitality/reservation-noshow-check.yaml +20 -0
- package/jobs/inventory/inventory-count-discrepancy-check.yaml +38 -0
- package/jobs/inventory/low-stock-alert.yaml +20 -0
- package/jobs/investing/crypto-price-alert.yaml +33 -0
- package/jobs/investing/portfolio-rebalance-check.yaml +32 -0
- package/jobs/learning/cert-renewal-reminder.yaml +30 -0
- package/jobs/learning/conference-cfp-deadline-reminder.yaml +42 -0
- package/jobs/legal/contract-renewal-reminder.yaml +31 -0
- package/jobs/legal/trademark-renewal-reminder.yaml +30 -0
- package/jobs/logistics/customs-clearance-check.yaml +34 -0
- package/jobs/logistics/shipment-delay-watch.yaml +38 -0
- package/jobs/manufacturing/production-line-downtime-watch.yaml +34 -0
- package/jobs/manufacturing/quality-defect-rate-check.yaml +20 -0
- package/jobs/marketing/ad-spend-pacing-check.yaml +37 -0
- package/jobs/marketing/email-deliverability-check.yaml +37 -0
- package/jobs/nonprofit/grant-deadline-reminder.yaml +44 -0
- package/jobs/nonprofit/lapsed-donor-check.yaml +26 -0
- package/jobs/personal/medication-refill-reminder.yaml +30 -0
- package/jobs/podcast/episode-publish-gap-check.yaml +29 -0
- package/jobs/podcast/sponsor-deliverable-tracker.yaml +31 -0
- package/jobs/productivity/calendar-double-booking-check.yaml +21 -0
- package/jobs/productivity/stale-todo-sweep.yaml +26 -0
- package/jobs/productivity/timezone-meeting-conflict-check.yaml +31 -0
- package/jobs/realestate/lease-expiry-reminder.yaml +30 -0
- package/jobs/realestate/rental-vacancy-check.yaml +30 -0
- package/jobs/sales/lead-response-time-check.yaml +23 -0
- package/jobs/sales/stale-deal-nudge.yaml +35 -0
- package/jobs/security/2fa-enrollment-audit.yaml +24 -0
- package/jobs/security/cve-watch.yaml +27 -0
- package/jobs/security/dependabot-alert-digest.yaml +30 -0
- package/jobs/security/expiring-api-key-rotation.yaml +31 -0
- package/jobs/security/iam-key-rotation-reminder.yaml +27 -0
- package/jobs/security/s3-public-bucket-check.yaml +20 -0
- package/jobs/security/tls-cipher-weak-check.yaml +31 -0
- package/jobs/security/waf-rule-change-watch.yaml +38 -0
- package/jobs/support/csat-score-watch.yaml +32 -0
- package/jobs/support/ticket-backlog-aging-check.yaml +30 -0
- package/jobs/team/oncall-handoff-reminder.yaml +26 -0
- package/jobs/team/team-anniversary-reminder.yaml +22 -0
- package/jobs/travel/frequent-flyer-miles-expiry.yaml +30 -0
- package/jobs/travel/travel-insurance-expiry-check.yaml +26 -0
- package/package.json +1 -1
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
id: inspection-deadline-reminder
|
|
2
|
+
version: 1
|
|
3
|
+
name: Inspection Deadline Reminder
|
|
4
|
+
description: >
|
|
5
|
+
Warns you before a scheduled inspection date, so the site is actually
|
|
6
|
+
ready. Use this if an inspector has ever shown up to a site that wasn't
|
|
7
|
+
prepped because the date snuck up on the crew.
|
|
8
|
+
category: construction
|
|
9
|
+
tags: [construction, inspection, scheduling]
|
|
10
|
+
schedule: "0 7 * * *"
|
|
11
|
+
timezone: "UTC"
|
|
12
|
+
runner: shell
|
|
13
|
+
command: >
|
|
14
|
+
today=$(date +%s);
|
|
15
|
+
awk -F, -v today="$today" -v warn={{warn_days}} '
|
|
16
|
+
NR>1 {
|
|
17
|
+
cmd="date -d \"" $2 "\" +%s 2>/dev/null || date -jf \"%Y-%m-%d\" \"" $2 "\" +%s";
|
|
18
|
+
cmd | getline insp_ts; close(cmd);
|
|
19
|
+
days_left = int((insp_ts - today) / 86400);
|
|
20
|
+
if (days_left <= warn && days_left >= 0) print "WARNING: " $1 " inspection in " days_left " days (" $2 ")";
|
|
21
|
+
}
|
|
22
|
+
' {{inspections_csv}}
|
|
23
|
+
variables:
|
|
24
|
+
inspections_csv:
|
|
25
|
+
default: "inspections.csv"
|
|
26
|
+
description: "CSV with header row, columns: site_name,inspection_date(YYYY-MM-DD)."
|
|
27
|
+
warn_days:
|
|
28
|
+
default: 3
|
|
29
|
+
description: Days before the inspection to start warning.
|
|
30
|
+
compatible_agents: [generic, claude, codex]
|
|
31
|
+
notes: Keep inspections.csv updated as inspections get scheduled with the local authority.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
id: permit-expiry-check
|
|
2
|
+
version: 1
|
|
3
|
+
name: Building Permit Expiry Check
|
|
4
|
+
description: >
|
|
5
|
+
Warns you before a building permit expires so work doesn't get caught
|
|
6
|
+
without valid coverage. Use this if a permit has ever lapsed mid-project
|
|
7
|
+
and forced a costly re-inspection or re-application.
|
|
8
|
+
category: construction
|
|
9
|
+
tags: [construction, permits, compliance]
|
|
10
|
+
schedule: "0 8 * * 1"
|
|
11
|
+
timezone: "UTC"
|
|
12
|
+
runner: shell
|
|
13
|
+
command: >
|
|
14
|
+
today=$(date +%s);
|
|
15
|
+
awk -F, -v today="$today" -v warn={{warn_days}} '
|
|
16
|
+
NR>1 {
|
|
17
|
+
cmd="date -d \"" $2 "\" +%s 2>/dev/null || date -jf \"%Y-%m-%d\" \"" $2 "\" +%s";
|
|
18
|
+
cmd | getline exp_ts; close(cmd);
|
|
19
|
+
days_left = int((exp_ts - today) / 86400);
|
|
20
|
+
if (days_left <= warn) print "WARNING: permit \"" $1 "\" expires in " days_left " days (" $2 ")";
|
|
21
|
+
}
|
|
22
|
+
' {{permits_csv}}
|
|
23
|
+
variables:
|
|
24
|
+
permits_csv:
|
|
25
|
+
default: "permits.csv"
|
|
26
|
+
description: "CSV with header row, columns: permit_name,expiry_date(YYYY-MM-DD)."
|
|
27
|
+
warn_days:
|
|
28
|
+
default: 30
|
|
29
|
+
description: Days before expiry to start warning.
|
|
30
|
+
compatible_agents: [generic, claude, codex]
|
|
31
|
+
notes: Keep permits.csv updated per project/site — one row per active permit.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
id: canonical-tag-check
|
|
2
|
+
version: 1
|
|
3
|
+
name: Canonical Tag Check
|
|
4
|
+
description: >
|
|
5
|
+
Checks a list of pages for missing or self-conflicting canonical tags.
|
|
6
|
+
Use this if a templating bug has ever pointed every page's canonical at
|
|
7
|
+
the homepage (or nowhere at all) without anyone noticing.
|
|
8
|
+
category: content
|
|
9
|
+
tags: [seo, canonical, content]
|
|
10
|
+
schedule: "0 7 * * 1"
|
|
11
|
+
timezone: "UTC"
|
|
12
|
+
runner: shell
|
|
13
|
+
command: >
|
|
14
|
+
while IFS= read -r url; do
|
|
15
|
+
[ -z "$url" ] && continue;
|
|
16
|
+
canonical=$(curl -s "$url" | grep -o '<link[^>]*rel=["'"'"']canonical["'"'"'][^>]*>' | grep -o 'href=["'"'"'][^"'"'"']*' | sed 's/href=["'"'"']//');
|
|
17
|
+
if [ -z "$canonical" ]; then echo "MISSING canonical: $url";
|
|
18
|
+
elif [ "$canonical" != "$url" ]; then echo "MISMATCH: $url -> $canonical"; fi;
|
|
19
|
+
done < {{url_list_file}}
|
|
20
|
+
variables:
|
|
21
|
+
url_list_file:
|
|
22
|
+
default: "urls.txt"
|
|
23
|
+
description: Path to a file with one URL per line to check.
|
|
24
|
+
compatible_agents: [generic, claude, codex]
|
|
25
|
+
notes: Flags any canonical that doesn't exactly match the page URL — cross-check mismatches manually since some (e.g. tracking params stripped) are intentional.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
id: hreflang-audit
|
|
2
|
+
version: 1
|
|
3
|
+
name: Hreflang Audit
|
|
4
|
+
description: >
|
|
5
|
+
Checks a page's hreflang tags for missing reciprocal links or obviously
|
|
6
|
+
wrong language/region codes. Use this if a hreflang mistake has ever
|
|
7
|
+
quietly sent the wrong country's visitors to the wrong language version.
|
|
8
|
+
category: content
|
|
9
|
+
tags: [seo, hreflang, international]
|
|
10
|
+
schedule: "0 7 * * 1"
|
|
11
|
+
timezone: "UTC"
|
|
12
|
+
runner: shell
|
|
13
|
+
command: >
|
|
14
|
+
tags=$(curl -s {{page_url}} | grep -o '<link[^>]*rel=["'"'"']alternate["'"'"'][^>]*hreflang=["'"'"'][^"'"'"']*["'"'"'][^>]*>');
|
|
15
|
+
if [ -z "$tags" ]; then echo "WARNING: no hreflang tags found on {{page_url}}"; exit 1; fi;
|
|
16
|
+
echo "$tags" | grep -o 'hreflang=["'"'"'][^"'"'"']*' | sed 's/hreflang=["'"'"']//' | while read -r code; do
|
|
17
|
+
echo "$code" | grep -qE '^[a-z]{2}(-[A-Z]{2})?$|^x-default$' || echo "WARNING: suspicious hreflang code \"$code\" on {{page_url}}";
|
|
18
|
+
done;
|
|
19
|
+
echo "OK: found $(echo "$tags" | wc -l | tr -d ' ') hreflang tag(s) — verify reciprocal links manually"
|
|
20
|
+
variables:
|
|
21
|
+
page_url:
|
|
22
|
+
default: "https://example.com"
|
|
23
|
+
description: URL of the page to check.
|
|
24
|
+
compatible_agents: [generic, claude, codex]
|
|
25
|
+
notes: Flags malformed language/region codes and missing tags on this page only — checking reciprocal hreflang links across the whole site needs crawling every listed URL, which this job doesn't do.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
id: image-alt-text-audit
|
|
2
|
+
version: 1
|
|
3
|
+
name: Image Alt Text Audit
|
|
4
|
+
description: >
|
|
5
|
+
Checks a page for images missing alt text. Use this if images have ever
|
|
6
|
+
shipped without alt text because nobody double-checked before merging.
|
|
7
|
+
category: content
|
|
8
|
+
tags: [seo, accessibility, images]
|
|
9
|
+
schedule: "0 7 * * 1"
|
|
10
|
+
timezone: "UTC"
|
|
11
|
+
runner: shell
|
|
12
|
+
command: >
|
|
13
|
+
count=$(curl -s {{page_url}} | grep -o '<img[^>]*>' | grep -cv 'alt=');
|
|
14
|
+
if [ "$count" -gt 0 ]; then echo "WARNING: $count image(s) missing alt text on {{page_url}}"; exit 1;
|
|
15
|
+
else echo "OK: all images on {{page_url}} have alt text"; fi
|
|
16
|
+
variables:
|
|
17
|
+
page_url:
|
|
18
|
+
default: "https://example.com"
|
|
19
|
+
description: URL of the page to check.
|
|
20
|
+
compatible_agents: [generic, claude, codex]
|
|
21
|
+
notes: Flags images with no alt attribute at all — doesn't judge whether existing alt text is actually descriptive.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
id: page-speed-regression-watch
|
|
2
|
+
version: 1
|
|
3
|
+
name: Page Speed Regression Watch
|
|
4
|
+
description: >
|
|
5
|
+
Checks a page's load time against a baseline and flags a real
|
|
6
|
+
regression. Use this if a page has ever gotten slowly, silently slower
|
|
7
|
+
release after release until it was a real problem.
|
|
8
|
+
category: content
|
|
9
|
+
tags: [performance, seo, monitoring]
|
|
10
|
+
schedule: "0 6 * * *"
|
|
11
|
+
timezone: "UTC"
|
|
12
|
+
runner: shell
|
|
13
|
+
command: >
|
|
14
|
+
time_total=$(curl -s -o /dev/null -w '%{time_total}' {{page_url}});
|
|
15
|
+
if awk "BEGIN{exit !($time_total > {{threshold_seconds}})}"; then
|
|
16
|
+
echo "WARNING: {{page_url}} took ${time_total}s to load (threshold {{threshold_seconds}}s)"; exit 1;
|
|
17
|
+
else echo "OK: {{page_url}} loaded in ${time_total}s"; fi
|
|
18
|
+
variables:
|
|
19
|
+
page_url:
|
|
20
|
+
default: "https://example.com"
|
|
21
|
+
description: URL of the page to check.
|
|
22
|
+
threshold_seconds:
|
|
23
|
+
default: 3
|
|
24
|
+
description: Load time in seconds beyond which to warn.
|
|
25
|
+
compatible_agents: [generic, claude, codex]
|
|
26
|
+
notes: Measures raw TTFB-through-download time via curl, not real browser rendering — use a synthetic monitoring tool for full Core Web Vitals.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
id: sitemap-freshness-check
|
|
2
|
+
version: 1
|
|
3
|
+
name: Sitemap Freshness Check
|
|
4
|
+
description: >
|
|
5
|
+
Checks that your sitemap.xml was actually regenerated recently and isn't
|
|
6
|
+
quietly stuck on an old snapshot. Use this if your sitemap is generated
|
|
7
|
+
by a build step that's ever silently failed or skipped.
|
|
8
|
+
category: content
|
|
9
|
+
tags: [seo, sitemap, freshness]
|
|
10
|
+
schedule: "0 7 * * *"
|
|
11
|
+
timezone: "UTC"
|
|
12
|
+
runner: shell
|
|
13
|
+
command: >
|
|
14
|
+
lastmod=$(curl -s {{sitemap_url}} | grep -o '<lastmod>[^<]*' | sed 's/<lastmod>//' | sort -r | head -n1);
|
|
15
|
+
if [ -z "$lastmod" ]; then echo "WARNING: could not find any <lastmod> entries in {{sitemap_url}}"; exit 1;
|
|
16
|
+
else
|
|
17
|
+
lastmod_ts=$(date -d "$lastmod" +%s 2>/dev/null || date -jf "%Y-%m-%d" "${lastmod%%T*}" +%s 2>/dev/null);
|
|
18
|
+
now_ts=$(date +%s);
|
|
19
|
+
age_days=$(( (now_ts - lastmod_ts) / 86400 ));
|
|
20
|
+
if [ "$age_days" -ge "{{max_age_days}}" ]; then echo "WARNING: newest sitemap entry is $age_days days old"; exit 1;
|
|
21
|
+
else echo "OK: newest sitemap entry is $age_days days old"; fi
|
|
22
|
+
fi
|
|
23
|
+
variables:
|
|
24
|
+
sitemap_url:
|
|
25
|
+
default: "https://example.com/sitemap.xml"
|
|
26
|
+
description: URL of the sitemap to check.
|
|
27
|
+
max_age_days:
|
|
28
|
+
default: 14
|
|
29
|
+
description: Days since the newest lastmod entry before it's flagged stale.
|
|
30
|
+
compatible_agents: [generic, claude, codex]
|
|
31
|
+
notes: Assumes at least one <lastmod> tag exists in the sitemap; sitemap index files with nested sitemaps aren't followed.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
id: stale-post-audit
|
|
2
|
+
version: 1
|
|
3
|
+
name: Stale Post Audit
|
|
4
|
+
description: >
|
|
5
|
+
Flags published posts that haven't been touched in a long time, as
|
|
6
|
+
candidates for a refresh. Use this if old content quietly rots (dead
|
|
7
|
+
screenshots, outdated advice) while still ranking and getting traffic.
|
|
8
|
+
category: content
|
|
9
|
+
tags: [content, seo, maintenance]
|
|
10
|
+
schedule: "0 8 1 * *"
|
|
11
|
+
timezone: "UTC"
|
|
12
|
+
runner: agent-prompt
|
|
13
|
+
prompt: |
|
|
14
|
+
Review posts/pages under {{content_dir}}.
|
|
15
|
+
1. For each, find the last modified date (git log or frontmatter date).
|
|
16
|
+
2. Flag any not updated in more than {{stale_months}} months.
|
|
17
|
+
3. For the flagged ones, note anything obviously outdated (broken
|
|
18
|
+
screenshots, version numbers, dead links) if visible in the content.
|
|
19
|
+
4. Report the list ranked oldest-first.
|
|
20
|
+
variables:
|
|
21
|
+
content_dir:
|
|
22
|
+
default: "content/posts"
|
|
23
|
+
description: Directory containing published content.
|
|
24
|
+
stale_months:
|
|
25
|
+
default: 12
|
|
26
|
+
description: Months since last update before a post is flagged.
|
|
27
|
+
compatible_agents: [claude, codex, hermes, openclaw, generic]
|
|
28
|
+
notes: No generic script mode — "last modified" via git log is easy in shell, but judging what's outdated needs an agent reading the content.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
id: content-calendar-gap-check
|
|
2
|
+
version: 1
|
|
3
|
+
name: Content Calendar Gap Check
|
|
4
|
+
description: >
|
|
5
|
+
Checks that you have something scheduled to post in the next few days.
|
|
6
|
+
Use this if your publishing cadence has ever quietly broken because
|
|
7
|
+
nothing was queued and nobody noticed until the gap already showed.
|
|
8
|
+
category: creator
|
|
9
|
+
tags: [content, calendar, publishing]
|
|
10
|
+
schedule: "0 9 * * 1,4"
|
|
11
|
+
timezone: "UTC"
|
|
12
|
+
runner: shell
|
|
13
|
+
command: >
|
|
14
|
+
today=$(date +%s);
|
|
15
|
+
cutoff=$(( today + {{lookahead_days}} * 86400 ));
|
|
16
|
+
next_ts=$(awk -F, 'NR>1 {
|
|
17
|
+
cmd="date -d \"" $1 "\" +%s 2>/dev/null || date -jf \"%Y-%m-%d\" \"" $1 "\" +%s";
|
|
18
|
+
cmd | getline ts; close(cmd);
|
|
19
|
+
if (ts >= "'"$today"'") { print ts; exit }
|
|
20
|
+
}' {{schedule_csv}});
|
|
21
|
+
if [ -z "$next_ts" ] || [ "$next_ts" -gt "$cutoff" ]; then echo "WARNING: no post scheduled in the next {{lookahead_days}} days"; exit 1;
|
|
22
|
+
else echo "OK: next post is scheduled within {{lookahead_days}} days"; fi
|
|
23
|
+
variables:
|
|
24
|
+
schedule_csv:
|
|
25
|
+
default: "content-calendar.csv"
|
|
26
|
+
description: "CSV with header row, columns: publish_date(YYYY-MM-DD),title,platform."
|
|
27
|
+
lookahead_days:
|
|
28
|
+
default: 3
|
|
29
|
+
description: Days ahead that must have at least one scheduled post.
|
|
30
|
+
compatible_agents: [generic, claude, codex]
|
|
31
|
+
notes: Reads a plain CSV export of your content calendar — point schedule_csv at wherever your planning tool exports to.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
id: engagement-drop-watch
|
|
2
|
+
version: 1
|
|
3
|
+
name: Engagement Drop Watch
|
|
4
|
+
description: >
|
|
5
|
+
Compares recent post engagement to your baseline and flags a real drop.
|
|
6
|
+
Use this if you've ever kept posting into a falling algorithm curve for
|
|
7
|
+
weeks before noticing the numbers were down.
|
|
8
|
+
category: creator
|
|
9
|
+
tags: [content, engagement, social]
|
|
10
|
+
schedule: "0 9 * * 1"
|
|
11
|
+
timezone: "UTC"
|
|
12
|
+
runner: agent-prompt
|
|
13
|
+
prompt: |
|
|
14
|
+
Check engagement (likes, comments, shares, views — whatever the
|
|
15
|
+
platform reports) for posts on {{platform_hint}} over the last
|
|
16
|
+
{{recent_days}} days.
|
|
17
|
+
1. Compare average engagement rate to the prior {{baseline_days}}-day
|
|
18
|
+
baseline.
|
|
19
|
+
2. Flag a drop of {{drop_threshold_pct}}% or more.
|
|
20
|
+
3. If flagged, note anything that changed around the drop (posting time,
|
|
21
|
+
format, frequency) if it's visible from the data.
|
|
22
|
+
variables:
|
|
23
|
+
platform_hint:
|
|
24
|
+
default: "your primary platform (YouTube, Instagram, TikTok, etc.)"
|
|
25
|
+
description: Which platform's analytics to check.
|
|
26
|
+
recent_days:
|
|
27
|
+
default: 7
|
|
28
|
+
description: Recent window to evaluate.
|
|
29
|
+
baseline_days:
|
|
30
|
+
default: 30
|
|
31
|
+
description: Prior window used as the baseline for comparison.
|
|
32
|
+
drop_threshold_pct:
|
|
33
|
+
default: 25
|
|
34
|
+
description: Percent drop in engagement rate that counts as a real decline.
|
|
35
|
+
compatible_agents: [claude, codex, hermes, openclaw, generic]
|
|
36
|
+
notes: No generic script mode — platform analytics APIs vary widely and most need OAuth the agent may not have configured.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
id: cdn-cache-purge-reminder
|
|
2
|
+
version: 1
|
|
3
|
+
name: CDN Cache Purge Reminder
|
|
4
|
+
description: >
|
|
5
|
+
Reminds you to purge the CDN cache after a deploy, and can trigger it
|
|
6
|
+
directly if you give it credentials. Use this if you've ever shipped a
|
|
7
|
+
fix and then spent an hour confused why users still saw the old version.
|
|
8
|
+
category: devops
|
|
9
|
+
tags: [cdn, cache, deploy]
|
|
10
|
+
schedule: "*/30 * * * *"
|
|
11
|
+
timezone: "UTC"
|
|
12
|
+
runner: shell
|
|
13
|
+
command: >
|
|
14
|
+
if [ -z "{{deploy_marker_file}}" ] || [ ! -f "{{deploy_marker_file}}" ]; then echo "OK: no pending deploy marker found"; exit 0; fi;
|
|
15
|
+
echo "REMINDER: deploy marker found at {{deploy_marker_file}} — purge CDN cache for {{cdn_zone}} if not already done, then remove the marker.";
|
|
16
|
+
variables:
|
|
17
|
+
deploy_marker_file:
|
|
18
|
+
default: ".deploy-pending"
|
|
19
|
+
description: Path to a marker file your deploy script touches; job reminds until it's removed.
|
|
20
|
+
cdn_zone:
|
|
21
|
+
default: "your CDN zone/distribution"
|
|
22
|
+
description: Name of the CDN zone, for the reminder text.
|
|
23
|
+
compatible_agents: [generic, claude, codex]
|
|
24
|
+
notes: >
|
|
25
|
+
Deliberately doesn't call any CDN API directly since providers differ
|
|
26
|
+
widely (Cloudflare, Fastly, CloudFront) — have your deploy script touch
|
|
27
|
+
the marker file, and remove it once cache is purged.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
id: ci-build-time-regression-watch
|
|
2
|
+
version: 1
|
|
3
|
+
name: CI Build Time Regression Watch
|
|
4
|
+
description: >
|
|
5
|
+
Compares recent CI build durations to a baseline and flags a real
|
|
6
|
+
slowdown. Use this if build times have ever crept up gradually until a
|
|
7
|
+
30-second CI run became a 15-minute one.
|
|
8
|
+
category: devops
|
|
9
|
+
tags: [ci, performance, build-time]
|
|
10
|
+
schedule: "0 9 * * 1-5"
|
|
11
|
+
timezone: "UTC"
|
|
12
|
+
runner: agent-prompt
|
|
13
|
+
prompt: |
|
|
14
|
+
Check recent CI run durations for {{repo_hint}} over the last
|
|
15
|
+
{{recent_runs}} runs on the main branch.
|
|
16
|
+
1. Compute the average duration and compare to the average of the prior
|
|
17
|
+
{{baseline_runs}} runs.
|
|
18
|
+
2. Flag a regression of {{threshold_pct}}% or more.
|
|
19
|
+
3. If flagged, note which stage/job grew the most, if that breakdown is
|
|
20
|
+
available.
|
|
21
|
+
variables:
|
|
22
|
+
repo_hint:
|
|
23
|
+
default: "this repo's CI (GitHub Actions, CircleCI, etc.)"
|
|
24
|
+
description: Which repo and CI provider to check.
|
|
25
|
+
recent_runs:
|
|
26
|
+
default: 10
|
|
27
|
+
description: Number of recent runs to average for the current period.
|
|
28
|
+
baseline_runs:
|
|
29
|
+
default: 30
|
|
30
|
+
description: Number of prior runs to use as the baseline.
|
|
31
|
+
threshold_pct:
|
|
32
|
+
default: 30
|
|
33
|
+
description: Percent increase in average duration that counts as a regression.
|
|
34
|
+
compatible_agents: [claude, codex, hermes, openclaw, generic]
|
|
35
|
+
notes: No generic script mode — CI provider APIs vary, and per-stage timing breakdowns need provider-specific parsing.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
id: error-rate-spike-watch
|
|
2
|
+
version: 1
|
|
3
|
+
name: Error Rate Spike Watch
|
|
4
|
+
description: >
|
|
5
|
+
Checks your error tracker's recent error count against a threshold and
|
|
6
|
+
flags a spike. Use this if a bad deploy has ever quietly spiked errors
|
|
7
|
+
for hours before anyone noticed.
|
|
8
|
+
category: devops
|
|
9
|
+
tags: [errors, monitoring, alerting]
|
|
10
|
+
schedule: "*/15 * * * *"
|
|
11
|
+
timezone: "UTC"
|
|
12
|
+
runner: hybrid
|
|
13
|
+
command: >
|
|
14
|
+
if [ -n "$SENTRY_AUTH_TOKEN" ] && [ -n "{{sentry_project}}" ]; then
|
|
15
|
+
count=$(curl -s -H "Authorization: Bearer $SENTRY_AUTH_TOKEN" "https://sentry.io/api/0/projects/{{sentry_org}}/{{sentry_project}}/events/?statsPeriod=15m" | grep -o '"id"' | wc -l | tr -d ' ');
|
|
16
|
+
if [ "$count" -ge "{{threshold}}" ]; then echo "WARNING: $count errors in last 15m (threshold {{threshold}})"; exit 1;
|
|
17
|
+
else echo "OK: $count errors in last 15m"; fi
|
|
18
|
+
else
|
|
19
|
+
echo "SENTRY_AUTH_TOKEN or sentry_project not set — use agent-prompt mode instead";
|
|
20
|
+
fi
|
|
21
|
+
prompt: |
|
|
22
|
+
Check the error tracker (Sentry, Rollbar, Bugsnag, or whatever this
|
|
23
|
+
project uses) for {{sentry_project}} over the last 15 minutes.
|
|
24
|
+
1. Compare current error volume to the typical rate for this time of day.
|
|
25
|
+
2. If it's spiking (well above {{threshold}} events, or a clear anomaly
|
|
26
|
+
vs. baseline), alert with the top offending error and when it started.
|
|
27
|
+
3. If normal, report the count in one line.
|
|
28
|
+
script_note: >
|
|
29
|
+
`command` only supports Sentry's REST API with a raw event count
|
|
30
|
+
threshold. `prompt` works with any error tracker and can reason about
|
|
31
|
+
baseline vs. anomaly instead of a flat threshold.
|
|
32
|
+
variables:
|
|
33
|
+
sentry_org:
|
|
34
|
+
default: "your-org"
|
|
35
|
+
description: Sentry organization slug.
|
|
36
|
+
sentry_project:
|
|
37
|
+
default: "your-project"
|
|
38
|
+
description: Sentry project slug.
|
|
39
|
+
threshold:
|
|
40
|
+
default: 50
|
|
41
|
+
description: Error count in the window that counts as a spike.
|
|
42
|
+
compatible_agents: [claude, codex, hermes, openclaw, generic]
|
|
43
|
+
notes: Script mode needs SENTRY_AUTH_TOKEN in the environment; scoped read access to project events is enough.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
id: feature-flag-staleness-audit
|
|
2
|
+
version: 1
|
|
3
|
+
name: Feature Flag Staleness Audit
|
|
4
|
+
description: >
|
|
5
|
+
Flags feature flags that have been at 100% (or 0%) rollout for a long
|
|
6
|
+
time and never cleaned up. Use this if your flag list has become a
|
|
7
|
+
graveyard of decisions nobody removed the scaffolding for.
|
|
8
|
+
category: devops
|
|
9
|
+
tags: [feature-flags, cleanup, tech-debt]
|
|
10
|
+
schedule: "0 9 * * 1"
|
|
11
|
+
timezone: "UTC"
|
|
12
|
+
runner: agent-prompt
|
|
13
|
+
prompt: |
|
|
14
|
+
Audit feature flags in {{flag_provider_hint}} (or the flags config file
|
|
15
|
+
in this repo if flags are managed in code).
|
|
16
|
+
1. List flags that have been fully rolled out (100%) or fully killed (0%)
|
|
17
|
+
for more than {{stale_days}} days.
|
|
18
|
+
2. For each, note whether the flag and its dead branch are still
|
|
19
|
+
referenced in code.
|
|
20
|
+
3. Report the list, ranked by how long they've been stale, as candidates
|
|
21
|
+
for removal.
|
|
22
|
+
variables:
|
|
23
|
+
flag_provider_hint:
|
|
24
|
+
default: "LaunchDarkly"
|
|
25
|
+
description: Name of the feature flag system/provider in use (e.g. LaunchDarkly, Unleash, in-repo config).
|
|
26
|
+
stale_days:
|
|
27
|
+
default: 60
|
|
28
|
+
description: Days at a terminal rollout state before a flag counts as stale.
|
|
29
|
+
compatible_agents: [claude, codex, hermes, openclaw, generic]
|
|
30
|
+
notes: No generic script mode — flag providers have wildly different APIs, and "still referenced in code" needs a code-aware agent.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
id: k8s-pod-restart-watch
|
|
2
|
+
version: 1
|
|
3
|
+
name: Kubernetes Pod Restart Watch
|
|
4
|
+
description: >
|
|
5
|
+
Checks for pods with a high restart count and flags them. Use this if a
|
|
6
|
+
crash-looping pod has ever burned through hours before anyone noticed
|
|
7
|
+
it wasn't actually staying up.
|
|
8
|
+
category: devops
|
|
9
|
+
tags: [kubernetes, pods, monitoring]
|
|
10
|
+
schedule: "*/15 * * * *"
|
|
11
|
+
timezone: "UTC"
|
|
12
|
+
runner: shell
|
|
13
|
+
command: >
|
|
14
|
+
command -v kubectl >/dev/null 2>&1 || { echo "ERROR: kubectl not installed"; exit 1; };
|
|
15
|
+
kubectl get pods -n {{namespace}} --no-headers 2>/dev/null | awk -v threshold={{threshold}} '
|
|
16
|
+
{ restarts=$4+0; if (restarts >= threshold) print "WARNING: pod " $1 " has " restarts " restarts" }
|
|
17
|
+
'
|
|
18
|
+
variables:
|
|
19
|
+
namespace:
|
|
20
|
+
default: "default"
|
|
21
|
+
description: Kubernetes namespace to check.
|
|
22
|
+
threshold:
|
|
23
|
+
default: 5
|
|
24
|
+
description: Restart count that triggers a warning.
|
|
25
|
+
compatible_agents: [generic, claude, codex]
|
|
26
|
+
notes: Requires kubectl configured with a context pointing at the cluster; emits nothing if no pod is over threshold.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
id: log-forwarding-health-check
|
|
2
|
+
version: 1
|
|
3
|
+
name: Log Forwarding Health Check
|
|
4
|
+
description: >
|
|
5
|
+
Checks that logs are still actually arriving at your log aggregator.
|
|
6
|
+
Use this if a log shipper has ever silently died and nobody found out
|
|
7
|
+
until they needed logs that were never collected.
|
|
8
|
+
category: devops
|
|
9
|
+
tags: [logging, monitoring, observability]
|
|
10
|
+
schedule: "*/30 * * * *"
|
|
11
|
+
timezone: "UTC"
|
|
12
|
+
runner: shell
|
|
13
|
+
command: >
|
|
14
|
+
last_ts=$(curl -s -H "Authorization: Bearer {{log_api_token}}" "{{log_query_api_url}}" | grep -o '"timestamp":"[^"]*"' | sort -r | head -n1 | cut -d'"' -f4);
|
|
15
|
+
if [ -z "$last_ts" ]; then echo "WARNING: no recent log entries found via {{log_query_api_url}}"; exit 1; fi;
|
|
16
|
+
last_epoch=$(date -d "$last_ts" +%s 2>/dev/null);
|
|
17
|
+
now_epoch=$(date +%s);
|
|
18
|
+
minutes_since=$(( (now_epoch - last_epoch) / 60 ));
|
|
19
|
+
if [ "$minutes_since" -ge "{{max_gap_minutes}}" ]; then echo "WARNING: no new logs in $minutes_since minutes (last at $last_ts)"; exit 1;
|
|
20
|
+
else echo "OK: most recent log entry $minutes_since minutes ago"; fi
|
|
21
|
+
variables:
|
|
22
|
+
log_query_api_url:
|
|
23
|
+
default: "https://api.example-logs.com/query?limit=1&sort=desc"
|
|
24
|
+
description: Log aggregator API endpoint returning at least the most recent entry's timestamp.
|
|
25
|
+
log_api_token:
|
|
26
|
+
default: "your-api-token"
|
|
27
|
+
description: API token for the log aggregator.
|
|
28
|
+
max_gap_minutes:
|
|
29
|
+
default: 15
|
|
30
|
+
description: Minutes without a new log entry before it's flagged.
|
|
31
|
+
compatible_agents: [generic, claude, codex]
|
|
32
|
+
notes: Generic REST pattern — point log_query_api_url at your aggregator's (Datadog, Splunk, ELK) most-recent-entry query; adjust field names to match its response shape.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
id: staging-prod-config-diff
|
|
2
|
+
version: 1
|
|
3
|
+
name: Staging vs Production Config Diff
|
|
4
|
+
description: >
|
|
5
|
+
Diffs environment variable keys between staging and production and
|
|
6
|
+
flags mismatches. Use this if staging and prod have ever quietly
|
|
7
|
+
drifted apart until a deploy broke only in one of them.
|
|
8
|
+
category: devops
|
|
9
|
+
tags: [config, environments, drift]
|
|
10
|
+
schedule: "0 8 * * 1"
|
|
11
|
+
timezone: "UTC"
|
|
12
|
+
runner: shell
|
|
13
|
+
command: >
|
|
14
|
+
staging_keys=$(cut -d= -f1 {{staging_env_file}} | grep -v '^#' | sort);
|
|
15
|
+
prod_keys=$(cut -d= -f1 {{prod_env_file}} | grep -v '^#' | sort);
|
|
16
|
+
only_staging=$(comm -23 <(echo "$staging_keys") <(echo "$prod_keys"));
|
|
17
|
+
only_prod=$(comm -13 <(echo "$staging_keys") <(echo "$prod_keys"));
|
|
18
|
+
if [ -n "$only_staging" ] || [ -n "$only_prod" ]; then
|
|
19
|
+
echo "DRIFT DETECTED:";
|
|
20
|
+
[ -n "$only_staging" ] && echo "only in staging: $only_staging";
|
|
21
|
+
[ -n "$only_prod" ] && echo "only in prod: $only_prod";
|
|
22
|
+
exit 1;
|
|
23
|
+
else echo "OK: staging and prod env keys match"; fi
|
|
24
|
+
variables:
|
|
25
|
+
staging_env_file:
|
|
26
|
+
default: ".env.staging"
|
|
27
|
+
description: Path to the staging environment file (keys only compared, not values).
|
|
28
|
+
prod_env_file:
|
|
29
|
+
default: ".env.production"
|
|
30
|
+
description: Path to the production environment file.
|
|
31
|
+
compatible_agents: [generic, claude, codex]
|
|
32
|
+
notes: Compares key names only, never values, so secrets are never read or logged.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
id: terraform-drift-check
|
|
2
|
+
version: 1
|
|
3
|
+
name: Terraform Drift Check
|
|
4
|
+
description: >
|
|
5
|
+
Runs a Terraform plan and flags it if there's drift between your state
|
|
6
|
+
and actual infrastructure. Use this if you've ever had someone click
|
|
7
|
+
around in a cloud console and quietly break parity with your IaC.
|
|
8
|
+
category: devops
|
|
9
|
+
tags: [terraform, infrastructure, drift]
|
|
10
|
+
schedule: "0 7 * * 1-5"
|
|
11
|
+
timezone: "UTC"
|
|
12
|
+
runner: shell
|
|
13
|
+
command: >
|
|
14
|
+
cd {{terraform_dir}} && terraform plan -detailed-exitcode -no-color -input=false > /tmp/tf-plan.out 2>&1;
|
|
15
|
+
code=$?;
|
|
16
|
+
if [ "$code" -eq 2 ]; then echo "DRIFT DETECTED in {{terraform_dir}}:"; tail -n 40 /tmp/tf-plan.out; exit 1;
|
|
17
|
+
elif [ "$code" -eq 0 ]; then echo "OK: no drift in {{terraform_dir}}";
|
|
18
|
+
else echo "ERROR: terraform plan failed"; tail -n 40 /tmp/tf-plan.out; exit 1; fi
|
|
19
|
+
variables:
|
|
20
|
+
terraform_dir:
|
|
21
|
+
default: "."
|
|
22
|
+
description: Path to the Terraform root module to check.
|
|
23
|
+
compatible_agents: [generic, claude, codex]
|
|
24
|
+
notes: Requires terraform CLI and valid provider credentials already configured in the environment.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
id: assignment-grading-backlog-check
|
|
2
|
+
version: 1
|
|
3
|
+
name: Assignment Grading Backlog Check
|
|
4
|
+
description: >
|
|
5
|
+
Checks how many submitted assignments are still ungraded and flags it if
|
|
6
|
+
the backlog is growing. Use this if grading has ever piled up for weeks
|
|
7
|
+
until students started asking where their grades were.
|
|
8
|
+
category: education
|
|
9
|
+
tags: [education, grading, backlog]
|
|
10
|
+
schedule: "0 8 * * 1-5"
|
|
11
|
+
timezone: "UTC"
|
|
12
|
+
runner: shell
|
|
13
|
+
command: >
|
|
14
|
+
psql "{{database_url}}" -t -c "select course, count(*) from submissions where graded_at is null and submitted_at < now() - interval '{{stale_days}} days' group by course;"
|
|
15
|
+
variables:
|
|
16
|
+
database_url:
|
|
17
|
+
default: "postgres://user:pass@host:5432/db"
|
|
18
|
+
description: Connection string for the LMS/gradebook database.
|
|
19
|
+
stale_days:
|
|
20
|
+
default: 3
|
|
21
|
+
description: Days a submission can sit ungraded before it's counted in the backlog.
|
|
22
|
+
compatible_agents: [generic, claude, codex]
|
|
23
|
+
notes: Assumes a `submissions` table with `graded_at` and `submitted_at` — adjust the query for your LMS's schema or export.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
id: attendance-anomaly-check
|
|
2
|
+
version: 1
|
|
3
|
+
name: Attendance Anomaly Check
|
|
4
|
+
description: >
|
|
5
|
+
Flags students whose attendance has dropped sharply, before it becomes a
|
|
6
|
+
pattern nobody caught early. Use this if a student's attendance has ever
|
|
7
|
+
quietly fallen off and only got noticed at report-card time.
|
|
8
|
+
category: education
|
|
9
|
+
tags: [education, attendance, students]
|
|
10
|
+
schedule: "0 8 * * 1"
|
|
11
|
+
timezone: "UTC"
|
|
12
|
+
runner: agent-prompt
|
|
13
|
+
prompt: |
|
|
14
|
+
Review attendance records from {{sis_hint}} for the last
|
|
15
|
+
{{recent_weeks}} weeks.
|
|
16
|
+
1. Compare each student's recent attendance rate to their prior
|
|
17
|
+
baseline for the term.
|
|
18
|
+
2. Flag students with a drop of {{drop_threshold_pct}} percentage
|
|
19
|
+
points or more.
|
|
20
|
+
3. Report flagged students with their recent and baseline rates, so
|
|
21
|
+
follow-up (counselor, parent contact) can be prioritized.
|
|
22
|
+
variables:
|
|
23
|
+
sis_hint:
|
|
24
|
+
default: "your student information system"
|
|
25
|
+
description: Where attendance data lives.
|
|
26
|
+
recent_weeks:
|
|
27
|
+
default: 2
|
|
28
|
+
description: Recent window to evaluate.
|
|
29
|
+
drop_threshold_pct:
|
|
30
|
+
default: 20
|
|
31
|
+
description: Percentage-point drop in attendance rate that counts as an anomaly.
|
|
32
|
+
compatible_agents: [claude, codex, hermes, openclaw, generic]
|
|
33
|
+
notes: No generic script mode — SIS platforms vary widely and most need OAuth or export access the agent may not have configured.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
id: rsvp-followup-reminder
|
|
2
|
+
version: 1
|
|
3
|
+
name: RSVP Follow-up Reminder
|
|
4
|
+
description: >
|
|
5
|
+
Flags invitees who haven't RSVP'd as the event date gets close. Use this
|
|
6
|
+
if you've ever had to guess headcount because half the guest list never
|
|
7
|
+
replied and nobody chased them.
|
|
8
|
+
category: events
|
|
9
|
+
tags: [events, rsvp, planning]
|
|
10
|
+
schedule: "0 9 * * 1"
|
|
11
|
+
timezone: "UTC"
|
|
12
|
+
runner: shell
|
|
13
|
+
command: >
|
|
14
|
+
today=$(date +%s);
|
|
15
|
+
event_ts=$(date -d "{{event_date}}" +%s 2>/dev/null || date -jf "%Y-%m-%d" "{{event_date}}" +%s);
|
|
16
|
+
days_left=$(( (event_ts - today) / 86400 ));
|
|
17
|
+
if [ "$days_left" -gt "{{warn_days}}" ]; then echo "OK: event is $days_left days out, no follow-up needed yet"; exit 0; fi;
|
|
18
|
+
awk -F, 'NR>1 && $2 == "pending" {print "PENDING RSVP: " $1}' {{guest_list_csv}}
|
|
19
|
+
variables:
|
|
20
|
+
event_date:
|
|
21
|
+
default: "2026-12-01"
|
|
22
|
+
description: Date of the event (YYYY-MM-DD).
|
|
23
|
+
warn_days:
|
|
24
|
+
default: 14
|
|
25
|
+
description: Days before the event to start flagging pending RSVPs.
|
|
26
|
+
guest_list_csv:
|
|
27
|
+
default: "guest-list.csv"
|
|
28
|
+
description: "CSV with header row, columns: name,rsvp_status(pending/yes/no)."
|
|
29
|
+
compatible_agents: [generic, claude, codex]
|
|
30
|
+
notes: Keep guest-list.csv updated as RSVPs come in, or export it from your invite tool before each run.
|