@wonsukchoi/crondex 0.20.0 → 0.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/README.md +5 -1
  2. package/catalog.json +720 -17
  3. package/jobs/fieldservice/maintenance-contract-renewal-check.yaml +36 -0
  4. package/jobs/fieldservice/parts-low-stock-reorder-check.yaml +29 -0
  5. package/jobs/fieldservice/tech-eta-no-show-check.yaml +32 -0
  6. package/jobs/fieldservice/tech-license-renewal-check.yaml +36 -0
  7. package/jobs/fieldservice/unpaid-invoice-aging-check.yaml +35 -0
  8. package/jobs/fieldservice/unresolved-callback-tracker.yaml +35 -0
  9. package/jobs/fieldservice/warranty-claim-expiry-check.yaml +35 -0
  10. package/jobs/hr/{payroll-run-reminder.yaml → payroll-cutoff-checklist-reminder.yaml} +1 -1
  11. package/jobs/publishing/arc-review-copy-followup.yaml +35 -0
  12. package/jobs/publishing/isbn-registration-tracker.yaml +35 -0
  13. package/jobs/publishing/manuscript-deadline-tracker.yaml +34 -0
  14. package/jobs/publishing/permissions-clearance-tracker.yaml +36 -0
  15. package/jobs/publishing/print-run-reorder-threshold-check.yaml +32 -0
  16. package/jobs/publishing/rights-license-expiry-check.yaml +35 -0
  17. package/jobs/publishing/royalty-statement-due-check.yaml +33 -0
  18. package/jobs/spa/appointment-no-show-tracker.yaml +46 -0
  19. package/jobs/spa/gift-card-expiry-check.yaml +35 -0
  20. package/jobs/spa/license-renewal-tracker.yaml +35 -0
  21. package/jobs/spa/membership-unused-session-expiry-check.yaml +35 -0
  22. package/jobs/spa/product-chemical-expiry-check.yaml +35 -0
  23. package/jobs/spa/retail-product-low-stock-check.yaml +26 -0
  24. package/jobs/spa/safety-inspection-due-reminder.yaml +33 -0
  25. package/jobs/telecom/circuit-outage-detection.yaml +38 -0
  26. package/jobs/telecom/circuit-provisioning-order-aging.yaml +36 -0
  27. package/jobs/telecom/cpe-firmware-update-tracker.yaml +45 -0
  28. package/jobs/telecom/link-capacity-threshold-alert.yaml +37 -0
  29. package/jobs/telecom/peering-transit-contract-renewal-check.yaml +36 -0
  30. package/jobs/telecom/service-ticket-churn-risk-review.yaml +56 -0
  31. package/jobs/telecom/sla-uptime-breach-tracker.yaml +36 -0
  32. package/lib/category-descriptions.js +4 -0
  33. package/lib/duplicates-allowlist.js +5 -0
  34. package/package.json +1 -1
@@ -0,0 +1,36 @@
1
+ id: maintenance-contract-renewal-check
2
+ version: 1
3
+ name: Maintenance Contract Renewal Check
4
+ description: >
5
+ Checks recurring service/maintenance contracts (annual HVAC tune-ups,
6
+ quarterly plumbing inspections) against their renewal date and flags
7
+ any coming up so the customer can be rebooked before the contract
8
+ lapses. Use this if a maintenance customer has ever silently churned
9
+ because nobody called to renew before the term ran out.
10
+ category: fieldservice
11
+ tags: [fieldservice, maintenance-contract, renewal, recurring-revenue]
12
+ schedule: "0 8 * * 1"
13
+ timezone: "UTC"
14
+ runner: shell
15
+ command: >
16
+ today=$(date +%s);
17
+ awk -F',' -v today="$today" -v warn="{{warn_days_before}}" '
18
+ NR==1 {next}
19
+ $4 == "active" {
20
+ cmd = "date -d \"" $3 "\" +%s 2>/dev/null || date -j -f %Y-%m-%d \"" $3 "\" +%s 2>/dev/null";
21
+ cmd | getline renewal_epoch; close(cmd);
22
+ days_left = (renewal_epoch - today) / 86400;
23
+ if (days_left <= warn && days_left >= 0) {
24
+ printf "RENEWAL DUE: contract %s for %s — renews %s (%d days left)\n", $1, $2, $3, days_left;
25
+ }
26
+ }
27
+ ' "{{maintenance_contracts_csv_path}}"
28
+ variables:
29
+ maintenance_contracts_csv_path:
30
+ default: "./maintenance-contracts.csv"
31
+ description: "Path to a CSV with columns: contract_id,customer_name,renewal_date (YYYY-MM-DD),status (active/lapsed/cancelled)."
32
+ warn_days_before:
33
+ default: 21
34
+ description: Days before renewal to start warning, giving time to schedule the visit.
35
+ compatible_agents: [generic, claude, codex]
36
+ notes: Reach out to schedule the renewal visit once flagged — this job only surfaces the upcoming date, it doesn't book anything.
@@ -0,0 +1,29 @@
1
+ id: parts-low-stock-reorder-check
2
+ version: 1
3
+ name: Parts Low-Stock Reorder Check
4
+ description: >
5
+ Checks your truck/warehouse parts inventory against reorder thresholds
6
+ and flags anything running low before a tech shows up on a job without
7
+ the capacitor or valve they need. Use this if a job has ever been
8
+ rescheduled because a common part was quietly out of stock.
9
+ category: fieldservice
10
+ tags: [fieldservice, inventory, parts, reorder]
11
+ schedule: "0 6 * * 1-5"
12
+ timezone: "UTC"
13
+ runner: shell
14
+ command: >
15
+ awk -F',' '
16
+ NR==1 {next}
17
+ {
18
+ qty = $2 + 0; reorder_point = $3 + 0;
19
+ if (qty <= reorder_point) {
20
+ printf "LOW STOCK: %s — on hand %d (reorder point %d)\n", $1, qty, reorder_point;
21
+ }
22
+ }
23
+ ' "{{parts_inventory_csv_path}}"
24
+ variables:
25
+ parts_inventory_csv_path:
26
+ default: "./parts-inventory.csv"
27
+ description: "Path to a CSV with columns: part_name,quantity_on_hand,reorder_point."
28
+ compatible_agents: [generic, claude, codex]
29
+ notes: Place the reorder with your supplier once flagged — this job only surfaces the shortage, it doesn't place orders.
@@ -0,0 +1,32 @@
1
+ id: tech-eta-no-show-check
2
+ version: 1
3
+ name: Tech ETA No-Show Check
4
+ description: >
5
+ Checks today's dispatch log for jobs where the technician's promised
6
+ arrival window has passed with no check-in logged. Use this if a
7
+ customer has ever called asking where the tech is before dispatch
8
+ even noticed the appointment was running late.
9
+ category: fieldservice
10
+ tags: [fieldservice, dispatch, eta, no-show]
11
+ schedule: "*/30 7-18 * * 1-6"
12
+ timezone: "UTC"
13
+ runner: shell
14
+ command: >
15
+ now=$(date +%s);
16
+ awk -F',' -v now="$now" '
17
+ NR==1 {next}
18
+ $5 == "dispatched" {
19
+ cmd = "date -d \"" $3 "\" +%s 2>/dev/null || date -j -f %Y-%m-%d\\ %H:%M \"" $3 "\" +%s 2>/dev/null";
20
+ cmd | getline window_end_epoch; close(cmd);
21
+ if (now > window_end_epoch) {
22
+ late_min = (now - window_end_epoch) / 60;
23
+ printf "NO CHECK-IN: job %s — tech %s, window ended %s (%d min late)\n", $1, $2, $3, late_min;
24
+ }
25
+ }
26
+ ' "{{dispatch_log_csv_path}}"
27
+ variables:
28
+ dispatch_log_csv_path:
29
+ default: "./dispatch-log.csv"
30
+ description: "Path to a CSV with columns: job_id,tech_name,eta_window_end (YYYY-MM-DD HH:MM),customer_name,status (dispatched/checked-in/completed)."
31
+ compatible_agents: [generic, claude, codex]
32
+ notes: Call the tech directly once flagged — this job only surfaces the miss, it doesn't page anyone.
@@ -0,0 +1,36 @@
1
+ id: tech-license-renewal-check
2
+ version: 1
3
+ name: Tech License & Certification Renewal Check
4
+ description: >
5
+ Checks technician licenses and certifications (EPA 608, journeyman
6
+ electrician, plumbing license) against their expiration date and
7
+ flags any expiring soon. Use this if a tech has ever been pulled off
8
+ a job, or a permit rejected, because their certification quietly
9
+ lapsed without anyone tracking the renewal date.
10
+ category: fieldservice
11
+ tags: [fieldservice, license, certification, compliance]
12
+ schedule: "0 8 1 * *"
13
+ timezone: "UTC"
14
+ runner: shell
15
+ command: >
16
+ today=$(date +%s);
17
+ awk -F',' -v today="$today" -v warn="{{warn_days_before}}" '
18
+ NR==1 {next}
19
+ {
20
+ cmd = "date -d \"" $3 "\" +%s 2>/dev/null || date -j -f %Y-%m-%d \"" $3 "\" +%s 2>/dev/null";
21
+ cmd | getline expiry_epoch; close(cmd);
22
+ days_left = (expiry_epoch - today) / 86400;
23
+ if (days_left <= warn) {
24
+ printf "RENEWAL NEEDED: %s — %s expires %s (%d days left)\n", $1, $2, $3, days_left;
25
+ }
26
+ }
27
+ ' "{{tech_certifications_csv_path}}"
28
+ variables:
29
+ tech_certifications_csv_path:
30
+ default: "./tech-certifications.csv"
31
+ description: "Path to a CSV with columns: tech_name,certification_type,expiration_date (YYYY-MM-DD)."
32
+ warn_days_before:
33
+ default: 30
34
+ description: Days before expiration to start warning, giving time to renew.
35
+ compatible_agents: [generic, claude, codex]
36
+ notes: Confirm renewal requirements with the issuing body (EPA, state licensing board) — this job only tracks the date, it doesn't file anything.
@@ -0,0 +1,35 @@
1
+ id: unpaid-invoice-aging-check
2
+ version: 1
3
+ name: Unpaid Invoice Aging Check
4
+ description: >
5
+ Checks invoices issued after completed jobs against their due date
6
+ and flags any going unpaid past your collection threshold. Use this
7
+ if cash has ever gotten tight because completed jobs sat uncollected
8
+ for weeks with nobody following up on payment.
9
+ category: fieldservice
10
+ tags: [fieldservice, invoicing, collections, aging]
11
+ schedule: "0 9 * * 1-5"
12
+ timezone: "UTC"
13
+ runner: shell
14
+ command: >
15
+ today=$(date +%s);
16
+ awk -F',' -v today="$today" -v max_days="{{max_days_overdue}}" '
17
+ NR==1 {next}
18
+ $4 == "unpaid" {
19
+ cmd = "date -d \"" $3 "\" +%s 2>/dev/null || date -j -f %Y-%m-%d \"" $3 "\" +%s 2>/dev/null";
20
+ cmd | getline due_epoch; close(cmd);
21
+ overdue_days = (today - due_epoch) / 86400;
22
+ if (overdue_days >= max_days) {
23
+ printf "AGING: invoice %s for %s — $%s, due %s (%d days overdue)\n", $1, $2, $5, $3, overdue_days;
24
+ }
25
+ }
26
+ ' "{{invoices_csv_path}}"
27
+ variables:
28
+ invoices_csv_path:
29
+ default: "./invoices.csv"
30
+ description: "Path to a CSV with columns: invoice_id,customer_name,due_date (YYYY-MM-DD),status (unpaid/paid),amount."
31
+ max_days_overdue:
32
+ default: 14
33
+ description: Days past the due date before an unpaid invoice is flagged.
34
+ compatible_agents: [generic, claude, codex]
35
+ notes: Send a payment reminder or call the customer once flagged — this job only surfaces the aging balance, it doesn't send anything.
@@ -0,0 +1,35 @@
1
+ id: unresolved-callback-tracker
2
+ version: 1
3
+ name: Unresolved Callback Tracker
4
+ description: >
5
+ Flags customer callbacks (a return visit for the same issue within
6
+ the warranty window) that are still open past a set number of days.
7
+ Use this if a rework job has ever slipped through the cracks and the
8
+ customer had to call a second time to get it actually fixed.
9
+ category: fieldservice
10
+ tags: [fieldservice, callback, rework, quality]
11
+ schedule: "0 9 * * 1-5"
12
+ timezone: "UTC"
13
+ runner: shell
14
+ command: >
15
+ today=$(date +%s);
16
+ awk -F',' -v today="$today" -v max_days="{{max_open_days}}" '
17
+ NR==1 {next}
18
+ $4 == "open" {
19
+ cmd = "date -d \"" $2 "\" +%s 2>/dev/null || date -j -f %Y-%m-%d \"" $2 "\" +%s 2>/dev/null";
20
+ cmd | getline reported_epoch; close(cmd);
21
+ open_days = (today - reported_epoch) / 86400;
22
+ if (open_days >= max_days) {
23
+ printf "STALE CALLBACK: %s — original job %s, open %d days, tech %s\n", $1, $3, open_days, $5;
24
+ }
25
+ }
26
+ ' "{{callbacks_csv_path}}"
27
+ variables:
28
+ callbacks_csv_path:
29
+ default: "./callbacks.csv"
30
+ description: "Path to a CSV with columns: callback_id,reported_date (YYYY-MM-DD),original_job_id,status (open/resolved),assigned_tech."
31
+ max_open_days:
32
+ default: 3
33
+ description: How many days a callback can stay open before it's flagged as stale.
34
+ compatible_agents: [generic, claude, codex]
35
+ notes: Reassign or escalate the callback once flagged — this job only surfaces aging rework, it doesn't dispatch anyone.
@@ -0,0 +1,35 @@
1
+ id: warranty-claim-expiry-check
2
+ version: 1
3
+ name: Warranty Claim Expiry Check
4
+ description: >
5
+ Checks open equipment warranty claims (HVAC units, water heaters,
6
+ appliances) against the manufacturer's filing deadline and flags any
7
+ about to lapse unfiled. Use this if a claim has ever been denied
8
+ because it was submitted a day after the manufacturer's window closed.
9
+ category: fieldservice
10
+ tags: [fieldservice, warranty, claims, deadline]
11
+ schedule: "0 8 * * 1-5"
12
+ timezone: "UTC"
13
+ runner: shell
14
+ command: >
15
+ today=$(date +%s);
16
+ awk -F',' -v today="$today" -v warn="{{warn_days_before}}" '
17
+ NR==1 {next}
18
+ $4 == "open" {
19
+ cmd = "date -d \"" $3 "\" +%s 2>/dev/null || date -j -f %Y-%m-%d \"" $3 "\" +%s 2>/dev/null";
20
+ cmd | getline deadline_epoch; close(cmd);
21
+ days_left = (deadline_epoch - today) / 86400;
22
+ if (days_left <= warn) {
23
+ printf "EXPIRING: claim %s for job %s — due %s (%d days left)\n", $1, $2, $3, days_left;
24
+ }
25
+ }
26
+ ' "{{warranty_claims_csv_path}}"
27
+ variables:
28
+ warranty_claims_csv_path:
29
+ default: "./warranty-claims.csv"
30
+ description: "Path to a CSV with columns: claim_id,job_id,filing_deadline (YYYY-MM-DD),status (open/submitted)."
31
+ warn_days_before:
32
+ default: 5
33
+ description: Days before the filing deadline to start warning.
34
+ compatible_agents: [generic, claude, codex]
35
+ notes: Filing windows vary by manufacturer (Carrier, Trane, Rheem, etc.) — keep warranty-claims.csv current from your service management system export.
@@ -1,4 +1,4 @@
1
- id: payroll-run-reminder
1
+ id: payroll-cutoff-checklist-reminder
2
2
  version: 1
3
3
  name: Payroll Run Cutoff Reminder
4
4
  description: >
@@ -0,0 +1,35 @@
1
+ id: arc-review-copy-followup
2
+ version: 1
3
+ name: ARC Review Copy Followup
4
+ description: >
5
+ Flags reviewers, bloggers, or media contacts who received an advance
6
+ review copy (ARC) but haven't posted or filed a review within a set
7
+ window, so a nudge can go out before the publication date. Use this if
8
+ ARCs have ever been sent out and quietly forgotten with no review to show
9
+ for them.
10
+ category: publishing
11
+ tags: [publishing, arc, review-copies, marketing]
12
+ schedule: "0 9 * * 1"
13
+ timezone: "UTC"
14
+ runner: shell
15
+ command: >
16
+ today=$(date +%s);
17
+ awk -F',' -v today="$today" -v follow={{followup_days}} '
18
+ NR>1 && $4 == "no" {
19
+ cmd="date -d \"" $3 "\" +%s 2>/dev/null || date -jf \"%Y-%m-%d\" \"" $3 "\" +%s";
20
+ cmd | getline sent_ts; close(cmd);
21
+ days_since = int((today - sent_ts) / 86400);
22
+ if (days_since >= follow) print "FOLLOW UP: " $2 " received ARC for \"" $1 "\" " days_since " days ago, no review posted";
23
+ }
24
+ ' "{{arc_recipients_csv}}"
25
+ variables:
26
+ arc_recipients_csv:
27
+ default: "./arc-recipients.csv"
28
+ description: "CSV with header row, columns: title,recipient,sent_date(YYYY-MM-DD),review_posted(yes|no)."
29
+ followup_days:
30
+ default: 21
31
+ description: Days after sending an ARC to wait before flagging a followup nudge.
32
+ compatible_agents: [generic, claude, codex]
33
+ notes: >
34
+ Mark review_posted=yes in arc-recipients.csv as reviews come in so they
35
+ stop being flagged. Pair with your publicist's contact list export.
@@ -0,0 +1,35 @@
1
+ id: isbn-registration-tracker
2
+ version: 1
3
+ name: ISBN Registration Tracker
4
+ description: >
5
+ Flags upcoming titles that don't yet have an ISBN assigned and registered
6
+ with the relevant agency, checked against their planned publication date.
7
+ Use this if a title has ever hit its pub date without an ISBN because
8
+ registration wasn't started early enough.
9
+ category: publishing
10
+ tags: [publishing, isbn, metadata, pre-press]
11
+ schedule: "0 9 * * 1"
12
+ timezone: "UTC"
13
+ runner: shell
14
+ command: >
15
+ today=$(date +%s);
16
+ awk -F',' -v today="$today" -v lead={{lead_days}} '
17
+ NR>1 {
18
+ cmd="date -d \"" $2 "\" +%s 2>/dev/null || date -jf \"%Y-%m-%d\" \"" $2 "\" +%s";
19
+ cmd | getline pub_ts; close(cmd);
20
+ days_left = int((pub_ts - today) / 86400);
21
+ if ($3 == "" && days_left <= lead) print "MISSING ISBN: \"" $1 "\" publishes in " days_left " days (" $2 ") — no ISBN registered";
22
+ }
23
+ ' "{{titles_csv}}"
24
+ variables:
25
+ titles_csv:
26
+ default: "./upcoming-titles.csv"
27
+ description: "CSV with header row, columns: title,pub_date(YYYY-MM-DD),isbn(blank if not yet assigned)."
28
+ lead_days:
29
+ default: 60
30
+ description: Days before publication to start warning if an ISBN is still missing.
31
+ compatible_agents: [generic, claude, codex]
32
+ notes: >
33
+ Update upcoming-titles.csv as soon as an ISBN is assigned so the title
34
+ drops off the warning list. Registration lead time varies by agency, so
35
+ set lead_days to comfortably exceed your agency's typical turnaround.
@@ -0,0 +1,34 @@
1
+ id: manuscript-deadline-tracker
2
+ version: 1
3
+ name: Manuscript Deadline Tracker
4
+ description: >
5
+ Flags manuscript milestones (first draft, revisions, final delivery) coming
6
+ due from authors or editors. Use this if a book has ever slipped its
7
+ production schedule because a manuscript deadline only lived in an email
8
+ thread nobody rechecked.
9
+ category: publishing
10
+ tags: [publishing, manuscripts, authors, deadlines]
11
+ schedule: "0 9 * * 1-5"
12
+ timezone: "UTC"
13
+ runner: shell
14
+ command: >
15
+ today=$(date +%s);
16
+ awk -F',' -v today="$today" -v warn={{warn_days}} '
17
+ NR>1 {
18
+ cmd="date -d \"" $3 "\" +%s 2>/dev/null || date -jf \"%Y-%m-%d\" \"" $3 "\" +%s";
19
+ cmd | getline due_ts; close(cmd);
20
+ days_left = int((due_ts - today) / 86400);
21
+ if (days_left <= warn) print "DUE SOON: \"" $1 "\" (" $2 ") milestone due in " days_left " days (" $3 ")";
22
+ }
23
+ ' "{{manuscripts_csv}}"
24
+ variables:
25
+ manuscripts_csv:
26
+ default: "./manuscripts.csv"
27
+ description: "CSV with header row, columns: title,milestone(draft|revision|final),due_date(YYYY-MM-DD)."
28
+ warn_days:
29
+ default: 7
30
+ description: Days before a milestone due date to start warning.
31
+ compatible_agents: [generic, claude, codex]
32
+ notes: >
33
+ Keep manuscripts.csv updated with each title's next milestone as it's
34
+ scheduled or renegotiated with the author/editor.
@@ -0,0 +1,36 @@
1
+ id: permissions-clearance-tracker
2
+ version: 1
3
+ name: Permissions Clearance Tracker
4
+ description: >
5
+ Flags quoted material, images, lyrics, or other third-party content in a
6
+ forthcoming title that still needs permissions clearance before the book
7
+ goes to press. Use this if a title has ever gone to print with an
8
+ uncleared quote or image because clearance status wasn't tracked
9
+ centrally.
10
+ category: publishing
11
+ tags: [publishing, permissions, rights-clearance, pre-press]
12
+ schedule: "0 9 * * 1"
13
+ timezone: "UTC"
14
+ runner: shell
15
+ command: >
16
+ today=$(date +%s);
17
+ awk -F',' -v today="$today" -v lead={{lead_days}} '
18
+ NR>1 && $4 != "cleared" {
19
+ cmd="date -d \"" $2 "\" +%s 2>/dev/null || date -jf \"%Y-%m-%d\" \"" $2 "\" +%s";
20
+ cmd | getline pub_ts; close(cmd);
21
+ days_left = int((pub_ts - today) / 86400);
22
+ if (days_left <= lead) print "UNCLEARED: \"" $1 "\" — item \"" $3 "\" status=" $4 ", publishes in " days_left " days";
23
+ }
24
+ ' "{{permissions_csv}}"
25
+ variables:
26
+ permissions_csv:
27
+ default: "./permissions-clearances.csv"
28
+ description: "CSV with header row, columns: title,pub_date(YYYY-MM-DD),item_description,status(pending|requested|denied|cleared)."
29
+ lead_days:
30
+ default: 30
31
+ description: Days before publication to start warning about any item not yet marked cleared.
32
+ compatible_agents: [generic, claude, codex]
33
+ notes: >
34
+ Update permissions-clearances.csv as each request is sent, denied, or
35
+ cleared. A "denied" item still shows up here deliberately — it needs
36
+ editorial follow-up (cut or replace) before press, not just tracking.
@@ -0,0 +1,32 @@
1
+ id: print-run-reorder-threshold-check
2
+ version: 1
3
+ name: Print Run Reorder Threshold Check
4
+ description: >
5
+ Flags titles whose warehouse stock has dropped below the reorder
6
+ threshold, so a reprint can be queued before the book goes out of stock.
7
+ Use this if a title has ever gone unavailable for weeks because nobody
8
+ noticed the print run was running low until it was already sold out.
9
+ category: publishing
10
+ tags: [publishing, print-run, inventory, reprints]
11
+ schedule: "0 8 * * 1"
12
+ timezone: "UTC"
13
+ runner: shell
14
+ command: >
15
+ awk -F',' -v default_threshold={{default_reorder_threshold}} '
16
+ NR>1 {
17
+ threshold = ($3 != "" ? $3 : default_threshold);
18
+ if ($2+0 <= threshold+0) print "LOW STOCK: \"" $1 "\" at " $2 " units (reorder threshold " threshold ")";
19
+ }
20
+ ' "{{stock_csv}}"
21
+ variables:
22
+ stock_csv:
23
+ default: "./print-run-stock.csv"
24
+ description: "CSV with header row, columns: title,units_in_stock,reorder_threshold(optional, blank uses default)."
25
+ default_reorder_threshold:
26
+ default: 250
27
+ description: Fallback reorder threshold (in units) used when a title's row doesn't set its own.
28
+ compatible_agents: [generic, claude, codex]
29
+ notes: >
30
+ Update print-run-stock.csv from your distributor or warehouse inventory
31
+ export before each run. Reorder threshold should account for reprint
32
+ lead time, not just current demand.
@@ -0,0 +1,35 @@
1
+ id: rights-license-expiry-check
2
+ version: 1
3
+ name: Rights and License Expiry Check
4
+ description: >
5
+ Warns you before a granted or acquired rights/licensing deal (foreign
6
+ rights, film/TV options, audio, translation) expires or comes up for
7
+ renewal. Use this if a rights deal has ever lapsed silently because the
8
+ expiry date only lived in the signed contract's PDF.
9
+ category: publishing
10
+ tags: [publishing, rights, licensing, contracts]
11
+ schedule: "0 9 * * 1"
12
+ timezone: "UTC"
13
+ runner: shell
14
+ command: >
15
+ today=$(date +%s);
16
+ awk -F',' -v today="$today" -v warn={{warn_days}} '
17
+ NR>1 {
18
+ cmd="date -d \"" $3 "\" +%s 2>/dev/null || date -jf \"%Y-%m-%d\" \"" $3 "\" +%s";
19
+ cmd | getline exp_ts; close(cmd);
20
+ days_left = int((exp_ts - today) / 86400);
21
+ if (days_left <= warn) print "WARNING: " $2 " rights for \"" $1 "\" expire in " days_left " days (" $3 ")";
22
+ }
23
+ ' "{{rights_csv}}"
24
+ variables:
25
+ rights_csv:
26
+ default: "./rights-licenses.csv"
27
+ description: "CSV with header row, columns: title,rights_type(foreign|film|audio|translation|other),expiry_date(YYYY-MM-DD)."
28
+ warn_days:
29
+ default: 45
30
+ description: Days before a rights expiry date to start warning, so renegotiation or renewal can start in time.
31
+ compatible_agents: [generic, claude, codex]
32
+ notes: >
33
+ Covers both rights you've acquired (e.g. translation rights into a
34
+ language) and rights you've granted out (e.g. a film option). Keep
35
+ rights-licenses.csv updated from your contracts database.
@@ -0,0 +1,33 @@
1
+ id: royalty-statement-due-check
2
+ version: 1
3
+ name: Royalty Statement Due Check
4
+ description: >
5
+ Warns you before a royalty statement and payment is due to an author or
6
+ co-author. Use this if a royalty statement has ever gone out late (or
7
+ didn't go out at all) because the payout schedule wasn't tracked anywhere.
8
+ category: publishing
9
+ tags: [publishing, royalties, authors, payments]
10
+ schedule: "0 9 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 due_ts; close(cmd);
19
+ days_left = int((due_ts - today) / 86400);
20
+ if (days_left <= warn) print "WARNING: royalty statement for \"" $1 "\" due in " days_left " days (" $2 ")";
21
+ }
22
+ ' "{{royalty_schedule_csv}}"
23
+ variables:
24
+ royalty_schedule_csv:
25
+ default: "./royalty-schedule.csv"
26
+ description: "CSV with header row, columns: author_or_title,statement_due_date(YYYY-MM-DD)."
27
+ warn_days:
28
+ default: 14
29
+ description: Days before a statement due date to start warning.
30
+ compatible_agents: [generic, claude, codex]
31
+ notes: >
32
+ Most contracts pay semiannually or quarterly on fixed dates — keep
33
+ royalty-schedule.csv in sync with each contract's payout cadence.
@@ -0,0 +1,46 @@
1
+ id: appointment-no-show-tracker
2
+ version: 1
3
+ name: Appointment No-Show & Late-Cancel Tracker
4
+ description: >
5
+ Flags clients who no-showed or cancelled late in the past window so front
6
+ desk can follow up or apply a policy. Use this if a chair or treatment
7
+ room has ever sat empty because a client skipped without warning and
8
+ nobody noticed the pattern until it kept happening.
9
+ category: spa
10
+ tags: [spa, appointments, no-show, front-desk]
11
+ schedule: "0 18 * * *"
12
+ timezone: "UTC"
13
+ runner: shell
14
+ command: >
15
+ awk -F',' -v days="{{lookback_days}}" -v threshold="{{repeat_threshold}}" '
16
+ NR==1 {next}
17
+ {
18
+ cmd = "date -d \"" $2 "\" +%s 2>/dev/null || date -j -f %Y-%m-%d \"" $2 "\" +%s 2>/dev/null";
19
+ cmd | getline appt_epoch; close(cmd);
20
+ "date +%s" | getline now_epoch; close("date +%s");
21
+ diff_days = (now_epoch - appt_epoch) / 86400;
22
+ if (diff_days >= 0 && diff_days <= days && ($3 == "no-show" || $3 == "late-cancel")) {
23
+ count[$1]++;
24
+ printf "FLAGGED: %s — %s on %s\n", $1, $3, $2;
25
+ }
26
+ }
27
+ END {
28
+ for (client in count) {
29
+ if (count[client] >= threshold) {
30
+ printf "REPEAT OFFENDER: %s — %d no-show/late-cancel(s) in last %d days\n", client, count[client], days;
31
+ }
32
+ }
33
+ }
34
+ ' "{{appointments_csv_path}}"
35
+ variables:
36
+ appointments_csv_path:
37
+ default: "./appointments.csv"
38
+ description: "Path to a CSV with columns: client_name,appointment_date (YYYY-MM-DD),status (no-show,late-cancel,completed,etc)."
39
+ lookback_days:
40
+ default: 30
41
+ description: How many days back to scan for no-shows and late cancels.
42
+ repeat_threshold:
43
+ default: 2
44
+ description: Number of no-show/late-cancel incidents in the lookback window before flagging a client as a repeat offender.
45
+ compatible_agents: [generic, claude, codex]
46
+ notes: Repeat offenders are good candidates for a deposit-required or confirm-by-text policy before their next booking.
@@ -0,0 +1,35 @@
1
+ id: gift-card-expiry-check
2
+ version: 1
3
+ name: Gift Card Expiry Check
4
+ description: >
5
+ Scans your gift card ledger for cards approaching their expiration date
6
+ with a remaining balance. Use this if a client has ever held an unused
7
+ gift card that quietly expired, turning a goodwill purchase into a
8
+ complaint at checkout.
9
+ category: spa
10
+ tags: [spa, gift-cards, retention, front-desk]
11
+ schedule: "0 9 * * 1"
12
+ timezone: "UTC"
13
+ runner: shell
14
+ command: >
15
+ awk -F',' -v days="{{warn_days_before}}" '
16
+ NR==1 {next}
17
+ $3 > 0 {
18
+ cmd = "date -d \"" $2 "\" +%s 2>/dev/null || date -j -f %Y-%m-%d \"" $2 "\" +%s 2>/dev/null";
19
+ cmd | getline exp_epoch; close(cmd);
20
+ "date +%s" | getline now_epoch; close("date +%s");
21
+ diff_days = (exp_epoch - now_epoch) / 86400;
22
+ if (diff_days <= days && diff_days >= 0) {
23
+ printf "GIFT CARD EXPIRING: %s — balance $%.2f, expires %s (%d days)\n", $1, $3, $2, diff_days;
24
+ }
25
+ }
26
+ ' "{{gift_cards_csv_path}}"
27
+ variables:
28
+ gift_cards_csv_path:
29
+ default: "./gift-cards.csv"
30
+ description: "Path to a CSV with columns: card_code_or_holder,expiry_date (YYYY-MM-DD),remaining_balance."
31
+ warn_days_before:
32
+ default: 30
33
+ description: How many days before expiry to start warning, so the holder can be reminded to redeem it.
34
+ compatible_agents: [generic, claude, codex]
35
+ notes: Check local law before letting balances actually expire — many states restrict or ban gift card expiration, so this may need to become a "reminder only" job.
@@ -0,0 +1,35 @@
1
+ id: license-renewal-tracker
2
+ version: 1
3
+ name: Esthetician/Cosmetologist License Renewal Tracker
4
+ description: >
5
+ Warns before a staff member's state license, certification, or
6
+ continuing-education deadline lapses. Use this if a technician has ever
7
+ shown up ready to work a shift, only to discover their license expired
8
+ last month and they can't legally touch a client.
9
+ category: spa
10
+ tags: [spa, licensing, compliance, staff]
11
+ schedule: "0 8 1 * *"
12
+ timezone: "UTC"
13
+ runner: shell
14
+ command: >
15
+ awk -F',' -v days="{{warn_days_before}}" '
16
+ NR==1 {next}
17
+ {
18
+ cmd = "date -d \"" $3 "\" +%s 2>/dev/null || date -j -f %Y-%m-%d \"" $3 "\" +%s 2>/dev/null";
19
+ cmd | getline exp_epoch; close(cmd);
20
+ "date +%s" | getline now_epoch; close("date +%s");
21
+ diff_days = (exp_epoch - now_epoch) / 86400;
22
+ if (diff_days <= days) {
23
+ printf "LICENSE EXPIRING: %s (%s) — expires %s (%d days)\n", $1, $2, $3, diff_days;
24
+ }
25
+ }
26
+ ' "{{licenses_csv_path}}"
27
+ variables:
28
+ licenses_csv_path:
29
+ default: "./staff-licenses.csv"
30
+ description: "Path to a CSV with columns: staff_name,license_type,expiry_date (YYYY-MM-DD)."
31
+ warn_days_before:
32
+ default: 30
33
+ description: How many days before expiry to start warning, leaving time to complete renewal or CE hours.
34
+ compatible_agents: [generic, claude, codex]
35
+ notes: A lapsed license can be a licensing-board violation for both the technician and the business, so warn early enough to complete any required CE hours.
@@ -0,0 +1,35 @@
1
+ id: membership-unused-session-expiry-check
2
+ version: 1
3
+ name: Membership/Package Unused-Session Expiry Check
4
+ description: >
5
+ Flags members or package holders whose prepaid sessions or membership
6
+ credits are about to expire unused. Use this if a client has ever paid
7
+ for a monthly facial membership, banked three unused visits, and let
8
+ them evaporate because nobody reminded them to book.
9
+ category: spa
10
+ tags: [spa, membership, churn, retention]
11
+ schedule: "0 9 * * 1"
12
+ timezone: "UTC"
13
+ runner: shell
14
+ command: >
15
+ awk -F',' -v days="{{warn_days_before}}" '
16
+ NR==1 {next}
17
+ $4 > 0 {
18
+ cmd = "date -d \"" $3 "\" +%s 2>/dev/null || date -j -f %Y-%m-%d \"" $3 "\" +%s 2>/dev/null";
19
+ cmd | getline exp_epoch; close(cmd);
20
+ "date +%s" | getline now_epoch; close("date +%s");
21
+ diff_days = (exp_epoch - now_epoch) / 86400;
22
+ if (diff_days <= days && diff_days >= 0) {
23
+ printf "CREDITS EXPIRING: %s — %d unused credit(s), expires %s (%d days)\n", $1, $4, $3, diff_days;
24
+ }
25
+ }
26
+ ' "{{memberships_csv_path}}"
27
+ variables:
28
+ memberships_csv_path:
29
+ default: "./memberships.csv"
30
+ description: "Path to a CSV with columns: member_name,plan_name,credit_expiry_date (YYYY-MM-DD),unused_credits."
31
+ warn_days_before:
32
+ default: 10
33
+ description: How many days before credit expiry to start warning, while there's still time to book.
34
+ compatible_agents: [generic, claude, codex]
35
+ notes: A member who repeatedly lets credits expire unused is a churn risk — treat this as a retention nudge, not just a "use it or lose it" notice.