@wonsukchoi/crondex 0.20.1 → 0.22.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 +20 -30
- package/catalog.json +3052 -81
- package/jobs/ecommerce/affiliate-commission-payout-check.yaml +38 -0
- package/jobs/ecommerce/back-in-stock-notification-backlog-check.yaml +30 -0
- package/jobs/ecommerce/bundle-component-stock-mismatch-check.yaml +37 -0
- package/jobs/ecommerce/chargeback-fraud-risk-order-review.yaml +43 -0
- package/jobs/ecommerce/competitor-price-watch.yaml +60 -0
- package/jobs/ecommerce/economic-nexus-threshold-check.yaml +43 -0
- package/jobs/ecommerce/failed-payment-dunning-check.yaml +35 -0
- package/jobs/ecommerce/marketplace-listing-sync-drift-check.yaml +48 -0
- package/jobs/ecommerce/product-feed-health-check.yaml +35 -0
- package/jobs/ecommerce/purchase-order-overdue-check.yaml +32 -0
- package/jobs/ecommerce/storefront-ssl-domain-expiry-check.yaml +46 -0
- package/jobs/ecommerce/vip-tier-reclassification-check.yaml +55 -0
- package/jobs/ecommerce/wishlist-abandonment-check.yaml +37 -0
- package/jobs/fieldservice/maintenance-contract-renewal-check.yaml +36 -0
- package/jobs/fieldservice/parts-low-stock-reorder-check.yaml +29 -0
- package/jobs/fieldservice/tech-eta-no-show-check.yaml +32 -0
- package/jobs/fieldservice/tech-license-renewal-check.yaml +36 -0
- package/jobs/fieldservice/unpaid-invoice-aging-check.yaml +35 -0
- package/jobs/fieldservice/unresolved-callback-tracker.yaml +35 -0
- package/jobs/fieldservice/warranty-claim-expiry-check.yaml +35 -0
- package/jobs/finance/accounts-payable-aging-check.yaml +40 -0
- package/jobs/finance/bank-statement-reconciliation-check.yaml +40 -0
- package/jobs/finance/budget-vs-actual-variance-report.yaml +38 -0
- package/jobs/finance/contractor-1099-threshold-tracker.yaml +43 -0
- package/jobs/finance/credit-utilization-watch.yaml +40 -0
- package/jobs/finance/duplicate-payment-detection.yaml +43 -0
- package/jobs/finance/expense-report-compliance-check.yaml +46 -0
- package/jobs/finance/late-fee-interest-risk-check.yaml +43 -0
- package/jobs/finance/loan-covenant-compliance-check.yaml +37 -0
- package/jobs/finance/month-end-close-checklist-tracker.yaml +39 -0
- package/jobs/finance/multi-account-cash-position-rollup.yaml +45 -0
- package/jobs/finance/petty-cash-float-reconciliation.yaml +43 -0
- package/jobs/finance/quarterly-estimated-tax-calculator.yaml +66 -0
- package/jobs/finance/vendor-early-pay-discount-tracker.yaml +45 -0
- package/jobs/healthcare/appointment-slot-utilization-check.yaml +56 -0
- package/jobs/healthcare/claims-denial-resubmission-check.yaml +43 -0
- package/jobs/healthcare/clinical-supply-low-stock-check.yaml +30 -0
- package/jobs/healthcare/controlled-substance-inventory-reconciliation.yaml +42 -0
- package/jobs/healthcare/hipaa-access-log-audit.yaml +74 -0
- package/jobs/healthcare/patient-balance-collections-aging-check.yaml +41 -0
- package/jobs/healthcare/patient-immunization-schedule-check.yaml +41 -0
- package/jobs/healthcare/patient-portal-message-backlog-check.yaml +39 -0
- package/jobs/healthcare/patient-satisfaction-survey-tracking.yaml +59 -0
- package/jobs/healthcare/prescription-refill-request-backlog-check.yaml +38 -0
- package/jobs/healthcare/prior-authorization-expiry-check.yaml +53 -0
- package/jobs/healthcare/staff-cme-credit-tracking.yaml +41 -0
- package/jobs/healthcare/telehealth-session-issue-check.yaml +51 -0
- package/jobs/hr/aca-fte-threshold-monitor.yaml +44 -0
- package/jobs/hr/cobra-notification-deadline-tracker.yaml +47 -0
- package/jobs/hr/compliance-training-completion-check.yaml +41 -0
- package/jobs/hr/eeo1-filing-deadline-reminder.yaml +37 -0
- package/jobs/hr/handbook-acknowledgment-tracking.yaml +34 -0
- package/jobs/hr/headcount-budget-variance-check.yaml +37 -0
- package/jobs/hr/leave-of-absence-return-tracker.yaml +42 -0
- package/jobs/hr/org-chart-manager-drift-check.yaml +40 -0
- package/jobs/hr/pay-equity-band-outlier-check.yaml +58 -0
- package/jobs/hr/pto-year-end-use-it-or-lose-it-check.yaml +49 -0
- package/jobs/hr/retirement-plan-enrollment-deadline-check.yaml +40 -0
- package/jobs/hr/workers-comp-claim-status-check.yaml +42 -0
- package/jobs/legal/conflict-of-interest-check-tracker.yaml +38 -0
- package/jobs/legal/corporate-minute-book-completeness-check.yaml +31 -0
- package/jobs/legal/data-privacy-request-deadline-tracker.yaml +61 -0
- package/jobs/legal/entity-authority-document-expiry-check.yaml +37 -0
- package/jobs/legal/legal-document-retention-purge-review.yaml +39 -0
- package/jobs/legal/litigation-hold-acknowledgment-tracker.yaml +40 -0
- package/jobs/legal/non-compete-expiry-tracker.yaml +37 -0
- package/jobs/legal/outside-counsel-invoice-budget-check.yaml +37 -0
- package/jobs/legal/settlement-payment-schedule-tracker.yaml +34 -0
- package/jobs/legal/timekeeper-billable-hours-compliance-check.yaml +39 -0
- package/jobs/legal/trademark-infringement-watch.yaml +43 -0
- package/jobs/legal/vendor-coi-expiry-tracker.yaml +37 -0
- package/jobs/publishing/arc-review-copy-followup.yaml +35 -0
- package/jobs/publishing/isbn-registration-tracker.yaml +35 -0
- package/jobs/publishing/manuscript-deadline-tracker.yaml +34 -0
- package/jobs/publishing/permissions-clearance-tracker.yaml +36 -0
- package/jobs/publishing/print-run-reorder-threshold-check.yaml +32 -0
- package/jobs/publishing/rights-license-expiry-check.yaml +35 -0
- package/jobs/publishing/royalty-statement-due-check.yaml +33 -0
- package/jobs/realestate/capital-reserve-fund-threshold-check.yaml +32 -0
- package/jobs/realestate/eviction-notice-deadline-tracker.yaml +37 -0
- package/jobs/realestate/landlord-insurance-claim-status-check.yaml +35 -0
- package/jobs/realestate/lease-renewal-offer-window-check.yaml +35 -0
- package/jobs/realestate/maintenance-request-sla-check.yaml +39 -0
- package/jobs/realestate/move-in-move-out-inspection-tracker.yaml +35 -0
- package/jobs/realestate/rent-increase-notice-deadline-check.yaml +54 -0
- package/jobs/realestate/rent-roll-vacancy-loss-report.yaml +32 -0
- package/jobs/realestate/rental-license-renewal-check.yaml +35 -0
- package/jobs/realestate/security-deposit-return-deadline-check.yaml +38 -0
- package/jobs/realestate/tenant-application-review-backlog-check.yaml +35 -0
- package/jobs/realestate/tenant-renters-insurance-compliance-check.yaml +35 -0
- package/jobs/realestate/utility-billback-reconciliation-check.yaml +41 -0
- package/jobs/sales/champion-departure-watch.yaml +44 -0
- package/jobs/sales/closed-lost-reason-audit.yaml +42 -0
- package/jobs/sales/commission-payout-tracker.yaml +32 -0
- package/jobs/sales/contract-renewal-opportunity-tracker.yaml +28 -0
- package/jobs/sales/discount-approval-pending-check.yaml +31 -0
- package/jobs/sales/forecast-submission-compliance-check.yaml +42 -0
- package/jobs/sales/multi-year-renewal-escalation-tracker.yaml +31 -0
- package/jobs/sales/pipeline-hygiene-audit.yaml +26 -0
- package/jobs/sales/poc-trial-conversion-tracker.yaml +29 -0
- package/jobs/sales/referral-followup-tracker.yaml +40 -0
- package/jobs/sales/territory-coverage-gap-check.yaml +43 -0
- package/jobs/spa/appointment-no-show-tracker.yaml +46 -0
- package/jobs/spa/gift-card-expiry-check.yaml +35 -0
- package/jobs/spa/license-renewal-tracker.yaml +35 -0
- package/jobs/spa/membership-unused-session-expiry-check.yaml +35 -0
- package/jobs/spa/product-chemical-expiry-check.yaml +35 -0
- package/jobs/spa/retail-product-low-stock-check.yaml +26 -0
- package/jobs/spa/safety-inspection-due-reminder.yaml +33 -0
- package/jobs/telecom/circuit-outage-detection.yaml +38 -0
- package/jobs/telecom/circuit-provisioning-order-aging.yaml +36 -0
- package/jobs/telecom/cpe-firmware-update-tracker.yaml +45 -0
- package/jobs/telecom/link-capacity-threshold-alert.yaml +37 -0
- package/jobs/telecom/peering-transit-contract-renewal-check.yaml +36 -0
- package/jobs/telecom/service-ticket-churn-risk-review.yaml +56 -0
- package/jobs/telecom/sla-uptime-breach-tracker.yaml +36 -0
- package/lib/category-descriptions.js +4 -0
- package/lib/duplicates-allowlist.js +10 -0
- package/package.json +2 -2
|
@@ -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.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
id: accounts-payable-aging-check
|
|
2
|
+
version: 1
|
|
3
|
+
name: Accounts Payable Aging Check
|
|
4
|
+
description: >
|
|
5
|
+
Buckets bills you owe (not invoices you've sent) into aging ranges —
|
|
6
|
+
current, 30, 60, 90+ days past due — so nothing quietly slips into a
|
|
7
|
+
late-fee zone. Use this if you or your business pay vendors on terms
|
|
8
|
+
and want a standing view of what's coming due versus already overdue.
|
|
9
|
+
category: finance
|
|
10
|
+
tags: [accounts-payable, bills, aging, finance]
|
|
11
|
+
schedule: "0 8 * * *"
|
|
12
|
+
timezone: "UTC"
|
|
13
|
+
runner: shell
|
|
14
|
+
command: >
|
|
15
|
+
file={{payables_file}};
|
|
16
|
+
[ -f "$file" ] || { echo "ERROR: $file not found"; exit 1; };
|
|
17
|
+
today=$(date +%s);
|
|
18
|
+
tail -n +2 "$file" | while IFS=, read -r vendor invoice_id amount due paid; do
|
|
19
|
+
[ "$paid" = "yes" ] && continue;
|
|
20
|
+
due_epoch=$(date -j -f %Y-%m-%d "$due" +%s 2>/dev/null || date -d "$due" +%s);
|
|
21
|
+
days=$(( (today-due_epoch)/86400 ));
|
|
22
|
+
if [ "$days" -le 0 ]; then bucket="current";
|
|
23
|
+
elif [ "$days" -le 30 ]; then bucket="1-30 days";
|
|
24
|
+
elif [ "$days" -le 60 ]; then bucket="31-60 days";
|
|
25
|
+
elif [ "$days" -le 90 ]; then bucket="61-90 days";
|
|
26
|
+
else bucket="90+ days"; fi;
|
|
27
|
+
echo "$bucket | $vendor invoice $invoice_id — \$$amount (due $due)";
|
|
28
|
+
done | sort
|
|
29
|
+
variables:
|
|
30
|
+
payables_file:
|
|
31
|
+
default: "./accounts-payable.csv"
|
|
32
|
+
description: >
|
|
33
|
+
CSV with header "vendor,invoice_id,amount,due_date,paid" (due_date
|
|
34
|
+
is YYYY-MM-DD, paid is yes/no) — bills you owe, not invoices you've
|
|
35
|
+
sent (see invoice-overdue-check for receivables).
|
|
36
|
+
compatible_agents: [generic, claude, codex]
|
|
37
|
+
notes: >
|
|
38
|
+
Zero-token. You maintain accounts-payable.csv yourself (mark paid=yes
|
|
39
|
+
once settled) — this is the payables mirror of invoice-overdue-check,
|
|
40
|
+
which tracks receivables instead.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
id: bank-statement-reconciliation-check
|
|
2
|
+
version: 1
|
|
3
|
+
name: Bank Statement Reconciliation Check
|
|
4
|
+
description: >
|
|
5
|
+
Compares your internal ledger against a bank/card statement export and
|
|
6
|
+
flags transactions present in one but not the other, plus any balance
|
|
7
|
+
mismatch. Use this if your books have ever quietly drifted from what
|
|
8
|
+
the bank actually shows and you only found out at tax time.
|
|
9
|
+
category: finance
|
|
10
|
+
tags: [reconciliation, bookkeeping, bank, finance]
|
|
11
|
+
schedule: "0 9 * * 1"
|
|
12
|
+
timezone: "UTC"
|
|
13
|
+
runner: shell
|
|
14
|
+
command: >
|
|
15
|
+
ledger={{ledger_csv}}; statement={{statement_csv}};
|
|
16
|
+
[ -f "$ledger" ] || { echo "ERROR: $ledger not found"; exit 1; };
|
|
17
|
+
[ -f "$statement" ] || { echo "ERROR: $statement not found"; exit 1; };
|
|
18
|
+
echo "-- in statement but missing from ledger --";
|
|
19
|
+
tail -n +2 "$statement" | cut -d, -f1,3 | sort > /tmp/_stmt_ids.$$;
|
|
20
|
+
tail -n +2 "$ledger" | cut -d, -f1,3 | sort > /tmp/_ledger_ids.$$;
|
|
21
|
+
comm -23 /tmp/_stmt_ids.$$ /tmp/_ledger_ids.$$;
|
|
22
|
+
echo "-- in ledger but missing from statement --";
|
|
23
|
+
comm -13 /tmp/_stmt_ids.$$ /tmp/_ledger_ids.$$;
|
|
24
|
+
rm -f /tmp/_stmt_ids.$$ /tmp/_ledger_ids.$$
|
|
25
|
+
variables:
|
|
26
|
+
ledger_csv:
|
|
27
|
+
default: "./ledger.csv"
|
|
28
|
+
description: >
|
|
29
|
+
CSV with header "date,description,amount" — your internal
|
|
30
|
+
bookkeeping record of transactions.
|
|
31
|
+
statement_csv:
|
|
32
|
+
default: "./bank-statement.csv"
|
|
33
|
+
description: >
|
|
34
|
+
CSV with header "date,description,amount" exported from your bank
|
|
35
|
+
or card provider for the same period.
|
|
36
|
+
compatible_agents: [generic, claude, codex]
|
|
37
|
+
notes: >
|
|
38
|
+
Zero-token, matches on date+amount only (description text often differs
|
|
39
|
+
between ledger and bank export) — near-matches on rounding or
|
|
40
|
+
same-day-different-amount won't be caught, review flagged rows by hand.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
id: budget-vs-actual-variance-report
|
|
2
|
+
version: 1
|
|
3
|
+
name: Budget vs. Actual Variance Report
|
|
4
|
+
description: >
|
|
5
|
+
Compares budgeted vs. actual spend across every category or department
|
|
6
|
+
in one pass and reports the percentage variance for each, not just a
|
|
7
|
+
single category's pass/fail. Use this if you need a monthly variance
|
|
8
|
+
report across a whole budget (department, project, or household), which
|
|
9
|
+
is different from budget-overspend-check watching one category's limit.
|
|
10
|
+
category: finance
|
|
11
|
+
tags: [budget, variance, finance, reporting]
|
|
12
|
+
schedule: "0 9 2 * *"
|
|
13
|
+
timezone: "UTC"
|
|
14
|
+
runner: shell
|
|
15
|
+
command: >
|
|
16
|
+
file={{budget_file}}; threshold={{variance_threshold_pct}};
|
|
17
|
+
[ -f "$file" ] || { echo "ERROR: $file not found"; exit 1; };
|
|
18
|
+
tail -n +2 "$file" | while IFS=, read -r category budgeted actual; do
|
|
19
|
+
variance=$(awk -v b="$budgeted" -v a="$actual" 'BEGIN{if(b==0){print "NA"} else {printf "%.1f", ((a-b)/b)*100}}');
|
|
20
|
+
if [ "$variance" = "NA" ]; then echo "$category: budget \$0, actual \$$actual (no budget set)"; continue; fi;
|
|
21
|
+
flag="";
|
|
22
|
+
if awk -v v="$variance" -v t="$threshold" 'BEGIN{exit !(v+0 > t || v+0 < -t)}'; then flag=" <-- OVER THRESHOLD"; fi;
|
|
23
|
+
echo "$category: budget \$$budgeted, actual \$$actual, variance ${variance}%$flag";
|
|
24
|
+
done
|
|
25
|
+
variables:
|
|
26
|
+
budget_file:
|
|
27
|
+
default: "./budget-vs-actual.csv"
|
|
28
|
+
description: >
|
|
29
|
+
CSV with header "category,budgeted,actual" — one row per
|
|
30
|
+
category/department for the current period.
|
|
31
|
+
variance_threshold_pct:
|
|
32
|
+
default: 10
|
|
33
|
+
description: Percentage-point variance (over or under) that triggers a flag.
|
|
34
|
+
compatible_agents: [generic, claude, codex]
|
|
35
|
+
notes: >
|
|
36
|
+
Zero-token. Distinct from budget-overspend-check, which watches a single
|
|
37
|
+
category against one hard dollar limit day-to-day — this one is a
|
|
38
|
+
periodic multi-category variance report across an entire budget.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
id: contractor-1099-threshold-tracker
|
|
2
|
+
version: 1
|
|
3
|
+
name: Contractor 1099 Threshold Tracker
|
|
4
|
+
description: >
|
|
5
|
+
Tracks year-to-date payments per contractor and flags anyone
|
|
6
|
+
approaching or past the tax reporting threshold that triggers a 1099.
|
|
7
|
+
Use this if you pay freelancers or contractors and don't want to
|
|
8
|
+
discover in January that you're missing W-9s for someone you owe a
|
|
9
|
+
filing for.
|
|
10
|
+
category: finance
|
|
11
|
+
tags: ["1099", contractors, tax, finance]
|
|
12
|
+
schedule: "0 9 1 * *"
|
|
13
|
+
timezone: "UTC"
|
|
14
|
+
runner: shell
|
|
15
|
+
command: >
|
|
16
|
+
file={{payments_file}}; threshold={{reporting_threshold}}; warn_pct={{warn_pct}};
|
|
17
|
+
[ -f "$file" ] || { echo "ERROR: $file not found"; exit 1; };
|
|
18
|
+
year=$(date +%Y);
|
|
19
|
+
awk -F, -v year="$year" -v threshold="$threshold" -v warnpct="$warn_pct" '
|
|
20
|
+
NR>1 && $3 ~ "^"year"-" { total[$1] += $2 }
|
|
21
|
+
END {
|
|
22
|
+
for (contractor in total) {
|
|
23
|
+
pct = (total[contractor] / threshold) * 100;
|
|
24
|
+
if (total[contractor] >= threshold) print "OVER THRESHOLD: " contractor " paid $" total[contractor] " this year (1099 required)";
|
|
25
|
+
else if (pct >= warnpct) printf "APPROACHING: %s paid $%.2f this year (%.0f%% of $%.0f threshold)\n", contractor, total[contractor], pct, threshold;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
' "$file"
|
|
29
|
+
variables:
|
|
30
|
+
payments_file:
|
|
31
|
+
default: "./contractor-payments.csv"
|
|
32
|
+
description: "CSV with header \"contractor,amount,date\" (date is YYYY-MM-DD), one row per payment."
|
|
33
|
+
reporting_threshold:
|
|
34
|
+
default: 600
|
|
35
|
+
description: Cumulative annual payment amount that triggers a 1099 filing requirement (US default is $600; adjust for your jurisdiction/year).
|
|
36
|
+
warn_pct:
|
|
37
|
+
default: 75
|
|
38
|
+
description: Percentage of the threshold at which to start warning ahead of a required filing.
|
|
39
|
+
compatible_agents: [generic, claude, codex]
|
|
40
|
+
notes: >
|
|
41
|
+
Zero-token. US-centric default threshold — verify current IRS rules
|
|
42
|
+
and any state-specific thresholds for your situation; this doesn't
|
|
43
|
+
file anything, it only flags who needs a W-9/1099.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
id: credit-utilization-watch
|
|
2
|
+
version: 1
|
|
3
|
+
name: Credit Utilization Watch
|
|
4
|
+
description: >
|
|
5
|
+
Checks the balance-to-limit ratio on a credit card or line of credit
|
|
6
|
+
and warns when utilization crosses a threshold. Use this if you want
|
|
7
|
+
to protect your credit score or stay within a business line of
|
|
8
|
+
credit's comfortable operating range, rather than finding out only
|
|
9
|
+
when a statement arrives.
|
|
10
|
+
category: finance
|
|
11
|
+
tags: [credit, utilization, finance]
|
|
12
|
+
schedule: "0 8 * * *"
|
|
13
|
+
timezone: "UTC"
|
|
14
|
+
runner: shell
|
|
15
|
+
command: >
|
|
16
|
+
balance={{current_balance}}; limit={{credit_limit}}; threshold={{warn_pct}};
|
|
17
|
+
util=$(awk -v b="$balance" -v l="$limit" 'BEGIN{if(l==0){print 0} else {printf "%.1f", (b/l)*100}}');
|
|
18
|
+
if awk -v u="$util" -v t="$threshold" 'BEGIN{exit !(u+0 >= t)}'; then
|
|
19
|
+
echo "WARNING: {{account_name}} utilization at ${util}% (\$$balance of \$$limit) — over ${threshold}% threshold";
|
|
20
|
+
else
|
|
21
|
+
echo "OK: {{account_name}} utilization at ${util}% (\$$balance of \$$limit)";
|
|
22
|
+
fi
|
|
23
|
+
variables:
|
|
24
|
+
account_name:
|
|
25
|
+
default: "business line of credit"
|
|
26
|
+
description: Label for the account being checked.
|
|
27
|
+
current_balance:
|
|
28
|
+
default: 0
|
|
29
|
+
description: Current outstanding balance — update this manually or via your bank export before each run.
|
|
30
|
+
credit_limit:
|
|
31
|
+
default: 10000
|
|
32
|
+
description: Total credit limit on the account.
|
|
33
|
+
warn_pct:
|
|
34
|
+
default: 30
|
|
35
|
+
description: Utilization percentage at or above which to warn (30% is a common credit-score-friendly ceiling).
|
|
36
|
+
compatible_agents: [generic, claude, codex]
|
|
37
|
+
notes: >
|
|
38
|
+
Zero-token. current_balance is a manual input (or piped in from a
|
|
39
|
+
balance-export script) — this job doesn't fetch live balances from any
|
|
40
|
+
bank API itself.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
id: duplicate-payment-detection
|
|
2
|
+
version: 1
|
|
3
|
+
name: Duplicate Payment Detection
|
|
4
|
+
description: >
|
|
5
|
+
Scans a payments/disbursements log for the same vendor and invoice
|
|
6
|
+
number (or same vendor/amount/date) paid more than once. Use this if
|
|
7
|
+
a bill has ever gotten paid twice because it was submitted through two
|
|
8
|
+
channels or reprocessed after a system hiccup.
|
|
9
|
+
category: finance
|
|
10
|
+
tags: [duplicate-payment, accounts-payable, fraud-prevention, finance]
|
|
11
|
+
schedule: "0 9 * * 1"
|
|
12
|
+
timezone: "UTC"
|
|
13
|
+
runner: shell
|
|
14
|
+
command: >
|
|
15
|
+
file={{payments_file}};
|
|
16
|
+
[ -f "$file" ] || { echo "ERROR: $file not found"; exit 1; };
|
|
17
|
+
echo "-- duplicate vendor+invoice_id --";
|
|
18
|
+
tail -n +2 "$file" | awk -F, '{key=$1"|"$2; count[key]++; rows[key]=rows[key]"\n " $0} END{for (k in count) if (count[k]>1) print "DUPLICATE: " k " paid " count[k] " times:" rows[k]}';
|
|
19
|
+
echo "-- same vendor+amount within {{same_amount_window_days}} day(s) --";
|
|
20
|
+
tail -n +2 "$file" | sort -t, -k1,1 -k4,4 | awk -F, -v win="{{same_amount_window_days}}" '
|
|
21
|
+
{
|
|
22
|
+
cmd="date -d \"" $4 "\" +%s 2>/dev/null || date -jf \"%Y-%m-%d\" \"" $4 "\" +%s";
|
|
23
|
+
cmd | getline ts; close(cmd);
|
|
24
|
+
key=$1"|"$3;
|
|
25
|
+
if (key == prevkey && (ts - prevts) <= win*86400) print "POSSIBLE DUPLICATE: " $1 " $" $3 " paid on " prevdate " and again on " $4;
|
|
26
|
+
prevkey=key; prevts=ts; prevdate=$4;
|
|
27
|
+
}
|
|
28
|
+
'
|
|
29
|
+
variables:
|
|
30
|
+
payments_file:
|
|
31
|
+
default: "./payments-log.csv"
|
|
32
|
+
description: >
|
|
33
|
+
CSV with header "vendor,invoice_id,amount,date" (date is
|
|
34
|
+
YYYY-MM-DD) — one row per outgoing payment made.
|
|
35
|
+
same_amount_window_days:
|
|
36
|
+
default: 14
|
|
37
|
+
description: Flag same vendor+amount payments made within this many days of each other, even without a matching invoice_id.
|
|
38
|
+
compatible_agents: [generic, claude, codex]
|
|
39
|
+
notes: >
|
|
40
|
+
Zero-token. Exact-match check on vendor+invoice_id catches clear
|
|
41
|
+
duplicates; the amount+window check is a heuristic for reprocessed
|
|
42
|
+
payments without a shared invoice_id — review flagged pairs before
|
|
43
|
+
assuming either is a real duplicate.
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
id: expense-report-compliance-check
|
|
2
|
+
version: 1
|
|
3
|
+
name: Expense Report Compliance Check
|
|
4
|
+
description: >
|
|
5
|
+
Scans submitted expense report line items for missing receipts or
|
|
6
|
+
amounts over your policy limit for that category. Use this if
|
|
7
|
+
reimbursements have ever gone out the door with a missing receipt or a
|
|
8
|
+
suspiciously large "meals" line nobody double-checked.
|
|
9
|
+
category: finance
|
|
10
|
+
tags: [expenses, compliance, policy, finance]
|
|
11
|
+
schedule: "0 9 * * 1"
|
|
12
|
+
timezone: "UTC"
|
|
13
|
+
runner: shell
|
|
14
|
+
command: >
|
|
15
|
+
file={{expenses_file}};
|
|
16
|
+
[ -f "$file" ] || { echo "ERROR: $file not found"; exit 1; };
|
|
17
|
+
tail -n +2 "$file" | while IFS=, read -r employee category amount has_receipt date; do
|
|
18
|
+
flagged="";
|
|
19
|
+
if [ "$has_receipt" != "yes" ] && awk "BEGIN{exit !($amount > {{receipt_required_over}})}"; then
|
|
20
|
+
flagged="$flagged missing-receipt";
|
|
21
|
+
fi;
|
|
22
|
+
limit=$(awk -F, -v cat="$category" '$1==cat{print $2}' {{category_limits_file}} 2>/dev/null);
|
|
23
|
+
if [ -n "$limit" ] && awk "BEGIN{exit !($amount > $limit)}"; then
|
|
24
|
+
flagged="$flagged over-limit(\$$limit)";
|
|
25
|
+
fi;
|
|
26
|
+
if [ -n "$flagged" ]; then echo "FLAGGED: $employee — $category \$$amount on $date —$flagged"; fi;
|
|
27
|
+
done
|
|
28
|
+
variables:
|
|
29
|
+
expenses_file:
|
|
30
|
+
default: "./expense-reports.csv"
|
|
31
|
+
description: >
|
|
32
|
+
CSV with header "employee,category,amount,has_receipt,date"
|
|
33
|
+
(has_receipt is yes/no, date is YYYY-MM-DD).
|
|
34
|
+
category_limits_file:
|
|
35
|
+
default: "./expense-category-limits.csv"
|
|
36
|
+
description: >
|
|
37
|
+
CSV with header "category,limit" giving the max allowed amount per
|
|
38
|
+
category; categories not listed are treated as unlimited.
|
|
39
|
+
receipt_required_over:
|
|
40
|
+
default: 25
|
|
41
|
+
description: Require a receipt for any expense above this amount.
|
|
42
|
+
compatible_agents: [generic, claude, codex]
|
|
43
|
+
notes: >
|
|
44
|
+
Zero-token. You export expense-reports.csv from whatever expense tool
|
|
45
|
+
you use (or fill it in by hand) — this doesn't connect to a live expense
|
|
46
|
+
platform.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
id: late-fee-interest-risk-check
|
|
2
|
+
version: 1
|
|
3
|
+
name: Late Fee & Interest Accrual Risk Check
|
|
4
|
+
description: >
|
|
5
|
+
Estimates the dollar cost of leaving an overdue bill unpaid by
|
|
6
|
+
projecting late fees and accrued interest against its grace period.
|
|
7
|
+
Use this if you want to know what an overdue balance is actually
|
|
8
|
+
costing you, not just that it's overdue (see accounts-payable-aging-check
|
|
9
|
+
for the plain aging list).
|
|
10
|
+
category: finance
|
|
11
|
+
tags: [late-fees, interest, accounts-payable, finance]
|
|
12
|
+
schedule: "0 9 * * *"
|
|
13
|
+
timezone: "UTC"
|
|
14
|
+
runner: shell
|
|
15
|
+
command: >
|
|
16
|
+
file={{payables_file}};
|
|
17
|
+
[ -f "$file" ] || { echo "ERROR: $file not found"; exit 1; };
|
|
18
|
+
today=$(date +%s);
|
|
19
|
+
tail -n +2 "$file" | while IFS=, read -r vendor amount due grace_days annual_rate_pct flat_fee paid; do
|
|
20
|
+
[ "$paid" = "yes" ] && continue;
|
|
21
|
+
due_epoch=$(date -j -f %Y-%m-%d "$due" +%s 2>/dev/null || date -d "$due" +%s);
|
|
22
|
+
days_over=$(( (today-due_epoch)/86400 ));
|
|
23
|
+
days_over_grace=$(( days_over - grace_days ));
|
|
24
|
+
if [ "$days_over_grace" -gt 0 ]; then
|
|
25
|
+
accrued=$(awk -v p="$amount" -v r="$annual_rate_pct" -v d="$days_over_grace" 'BEGIN{printf "%.2f", p*(r/100/365)*d}');
|
|
26
|
+
total_risk=$(awk -v a="$accrued" -v f="$flat_fee" 'BEGIN{printf "%.2f", a+f}');
|
|
27
|
+
echo "RISK: $vendor — \$$amount overdue, $days_over_grace day(s) past grace period, est. accrued cost so far: \$$total_risk (fee \$$flat_fee + interest \$$accrued)";
|
|
28
|
+
fi;
|
|
29
|
+
done
|
|
30
|
+
variables:
|
|
31
|
+
payables_file:
|
|
32
|
+
default: "./late-fee-risk.csv"
|
|
33
|
+
description: >
|
|
34
|
+
CSV with header
|
|
35
|
+
"vendor,amount,due_date,grace_days,annual_rate_pct,flat_fee,paid"
|
|
36
|
+
— grace_days is the interest-free window after due_date,
|
|
37
|
+
annual_rate_pct is the penalty APR once grace expires, flat_fee is
|
|
38
|
+
a one-time late fee.
|
|
39
|
+
compatible_agents: [generic, claude, codex]
|
|
40
|
+
notes: >
|
|
41
|
+
Zero-token, simple daily-accrual estimate (principal x rate/365 x
|
|
42
|
+
days) — not a substitute for the vendor/creditor's actual fee schedule,
|
|
43
|
+
which may compound or cap differently.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
id: loan-covenant-compliance-check
|
|
2
|
+
version: 1
|
|
3
|
+
name: Loan Covenant Compliance Check
|
|
4
|
+
description: >
|
|
5
|
+
Computes financial ratios required by a loan agreement (e.g. debt
|
|
6
|
+
service coverage, current ratio) from your latest financials and flags
|
|
7
|
+
any that breach the covenant threshold. Use this if a lender requires
|
|
8
|
+
you to maintain certain ratios and a breach could trigger default or a
|
|
9
|
+
call on the loan.
|
|
10
|
+
category: finance
|
|
11
|
+
tags: [loan, covenants, ratios, finance]
|
|
12
|
+
schedule: "0 9 1 * *"
|
|
13
|
+
timezone: "UTC"
|
|
14
|
+
runner: shell
|
|
15
|
+
command: >
|
|
16
|
+
file={{financials_file}};
|
|
17
|
+
[ -f "$file" ] || { echo "ERROR: $file not found"; exit 1; };
|
|
18
|
+
tail -n +2 "$file" | while IFS=, read -r ratio_name value min_required max_allowed; do
|
|
19
|
+
breach="";
|
|
20
|
+
if [ -n "$min_required" ] && awk -v v="$value" -v m="$min_required" 'BEGIN{exit !(v+0 < m+0)}'; then breach="below minimum ($min_required)"; fi;
|
|
21
|
+
if [ -n "$max_allowed" ] && awk -v v="$value" -v m="$max_allowed" 'BEGIN{exit !(v+0 > m+0)}'; then breach="above maximum ($max_allowed)"; fi;
|
|
22
|
+
if [ -n "$breach" ]; then echo "COVENANT BREACH: $ratio_name = $value — $breach"; else echo "OK: $ratio_name = $value"; fi;
|
|
23
|
+
done
|
|
24
|
+
variables:
|
|
25
|
+
financials_file:
|
|
26
|
+
default: "./loan-covenant-ratios.csv"
|
|
27
|
+
description: >
|
|
28
|
+
CSV with header "ratio_name,value,min_required,max_allowed" — one
|
|
29
|
+
row per covenant (leave min_required or max_allowed blank if that
|
|
30
|
+
side isn't part of the covenant). You compute/update the current
|
|
31
|
+
value each period from your financial statements.
|
|
32
|
+
compatible_agents: [generic, claude, codex]
|
|
33
|
+
notes: >
|
|
34
|
+
Zero-token, pure comparison. You calculate each ratio's current value
|
|
35
|
+
yourself (e.g. DSCR, current ratio, debt-to-equity) from your
|
|
36
|
+
financial statements — this doesn't derive ratios from raw
|
|
37
|
+
balance-sheet/income-statement data.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
id: month-end-close-checklist-tracker
|
|
2
|
+
version: 1
|
|
3
|
+
name: Month-End Close Checklist Tracker
|
|
4
|
+
description: >
|
|
5
|
+
Tracks a list of month-end financial close tasks (reconcile bank,
|
|
6
|
+
post accruals, review AR/AP, close subledgers, etc.) and flags
|
|
7
|
+
incomplete items as the close deadline approaches. Use this if your
|
|
8
|
+
monthly close has ever slipped a step because nobody had a single
|
|
9
|
+
place tracking whether every task actually got done.
|
|
10
|
+
category: finance
|
|
11
|
+
tags: [month-end-close, checklist, bookkeeping, finance]
|
|
12
|
+
schedule: "0 9 25 * *"
|
|
13
|
+
timezone: "UTC"
|
|
14
|
+
runner: shell
|
|
15
|
+
command: >
|
|
16
|
+
file={{checklist_file}}; close_day={{close_day_of_month}};
|
|
17
|
+
[ -f "$file" ] || { echo "ERROR: $file not found"; exit 1; };
|
|
18
|
+
today=$(date +%d);
|
|
19
|
+
incomplete=$(tail -n +2 "$file" | awk -F, '$2 != "done" {print}');
|
|
20
|
+
if [ -z "$incomplete" ]; then
|
|
21
|
+
echo "All month-end close tasks marked done.";
|
|
22
|
+
else
|
|
23
|
+
echo "INCOMPLETE close tasks (target close day: $close_day, today is day $today):";
|
|
24
|
+
echo "$incomplete" | awk -F, '{print " - " $1 " (" $2 ")"}';
|
|
25
|
+
fi
|
|
26
|
+
variables:
|
|
27
|
+
checklist_file:
|
|
28
|
+
default: "./month-end-close-checklist.csv"
|
|
29
|
+
description: >
|
|
30
|
+
CSV with header "task,status" (status is done/pending) — reset
|
|
31
|
+
status to pending for each task at the start of a new month.
|
|
32
|
+
close_day_of_month:
|
|
33
|
+
default: 5
|
|
34
|
+
description: Target day of the following month by which close should be finished (informational, shown in output).
|
|
35
|
+
compatible_agents: [generic, claude, codex]
|
|
36
|
+
notes: >
|
|
37
|
+
Zero-token. You maintain the checklist file and mark tasks done as you
|
|
38
|
+
complete them — this doesn't verify the underlying accounting work
|
|
39
|
+
itself, just whether each task is checked off.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
id: multi-account-cash-position-rollup
|
|
2
|
+
version: 1
|
|
3
|
+
name: Multi-Account Cash Position Rollup
|
|
4
|
+
description: >
|
|
5
|
+
Sums balances across multiple bank/cash accounts into one total
|
|
6
|
+
position and flags if the total or any single account drops below a
|
|
7
|
+
minimum threshold. Use this if cash is spread across several accounts
|
|
8
|
+
or entities and you want a single low-balance tripwire instead of
|
|
9
|
+
checking each account separately.
|
|
10
|
+
category: finance
|
|
11
|
+
tags: [cash, balances, multi-account, finance]
|
|
12
|
+
schedule: "0 8 * * *"
|
|
13
|
+
timezone: "UTC"
|
|
14
|
+
runner: shell
|
|
15
|
+
command: >
|
|
16
|
+
file={{balances_file}}; min_total={{min_total_balance}}; min_account={{min_per_account_balance}};
|
|
17
|
+
[ -f "$file" ] || { echo "ERROR: $file not found"; exit 1; };
|
|
18
|
+
total=0;
|
|
19
|
+
tail -n +2 "$file" | while IFS=, read -r account balance; do
|
|
20
|
+
if awk -v b="$balance" -v m="$min_account" 'BEGIN{exit !(b+0 < m+0)}'; then
|
|
21
|
+
echo "LOW: $account balance \$$balance is below per-account minimum \$$min_account";
|
|
22
|
+
fi;
|
|
23
|
+
done;
|
|
24
|
+
total=$(tail -n +2 "$file" | awk -F, '{sum+=$2} END{printf "%.2f", sum}');
|
|
25
|
+
echo "TOTAL CASH POSITION: \$$total across $(tail -n +2 "$file" | wc -l | tr -d ' ') accounts";
|
|
26
|
+
if awk -v t="$total" -v m="$min_total" 'BEGIN{exit !(t+0 < m+0)}'; then
|
|
27
|
+
echo "WARNING: total cash position \$$total is below minimum \$$min_total";
|
|
28
|
+
fi
|
|
29
|
+
variables:
|
|
30
|
+
balances_file:
|
|
31
|
+
default: "./account-balances.csv"
|
|
32
|
+
description: >
|
|
33
|
+
CSV with header "account,balance" — one row per account/entity,
|
|
34
|
+
updated manually or via bank export before each run.
|
|
35
|
+
min_total_balance:
|
|
36
|
+
default: 5000
|
|
37
|
+
description: Minimum acceptable combined cash position across all accounts.
|
|
38
|
+
min_per_account_balance:
|
|
39
|
+
default: 500
|
|
40
|
+
description: Minimum acceptable balance in any single account.
|
|
41
|
+
compatible_agents: [generic, claude, codex]
|
|
42
|
+
notes: >
|
|
43
|
+
Zero-token. balances are a manual/exported snapshot, not a live bank
|
|
44
|
+
feed — refresh account-balances.csv before each run for accurate
|
|
45
|
+
results.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
id: petty-cash-float-reconciliation
|
|
2
|
+
version: 1
|
|
3
|
+
name: Petty Cash Float Reconciliation
|
|
4
|
+
description: >
|
|
5
|
+
Checks that a petty cash log's starting float minus logged expenses
|
|
6
|
+
plus replenishments matches the expected remaining balance, and flags
|
|
7
|
+
any variance. Use this if a physical cash box or float has ever come
|
|
8
|
+
up short (or over) and nobody could explain why.
|
|
9
|
+
category: finance
|
|
10
|
+
tags: [petty-cash, reconciliation, cash, finance]
|
|
11
|
+
schedule: "0 9 * * 1"
|
|
12
|
+
timezone: "UTC"
|
|
13
|
+
runner: shell
|
|
14
|
+
command: >
|
|
15
|
+
file={{petty_cash_log}}; expected_on_hand={{expected_on_hand}}; tolerance={{tolerance}};
|
|
16
|
+
[ -f "$file" ] || { echo "ERROR: $file not found"; exit 1; };
|
|
17
|
+
starting=$(head -2 "$file" | tail -1 | cut -d, -f2);
|
|
18
|
+
net=$(awk -F, 'NR>1 { if ($3=="expense") sum -= $2; else if ($3=="replenishment") sum += $2 } END {print sum+0}' "$file");
|
|
19
|
+
computed=$(awk -v s="$starting" -v n="$net" 'BEGIN{printf "%.2f", s+n}');
|
|
20
|
+
variance=$(awk -v c="$computed" -v e="$expected_on_hand" 'BEGIN{printf "%.2f", c-e}');
|
|
21
|
+
if awk -v v="$variance" -v t="$tolerance" 'BEGIN{v=(v<0?-v:v); exit !(v > t)}'; then
|
|
22
|
+
echo "VARIANCE: computed balance \$$computed vs. counted on-hand \$$expected_on_hand (diff \$$variance) — investigate";
|
|
23
|
+
else
|
|
24
|
+
echo "OK: computed balance \$$computed matches counted on-hand \$$expected_on_hand within \$$tolerance";
|
|
25
|
+
fi
|
|
26
|
+
variables:
|
|
27
|
+
petty_cash_log:
|
|
28
|
+
default: "./petty-cash-log.csv"
|
|
29
|
+
description: >
|
|
30
|
+
CSV with header "date,amount,type,note" where type is
|
|
31
|
+
starting/expense/replenishment, first data row is the starting
|
|
32
|
+
float.
|
|
33
|
+
expected_on_hand:
|
|
34
|
+
default: 0
|
|
35
|
+
description: Actual counted cash currently in the box/float, entered manually after a physical count.
|
|
36
|
+
tolerance:
|
|
37
|
+
default: 5
|
|
38
|
+
description: Dollar variance allowed before flagging a discrepancy.
|
|
39
|
+
compatible_agents: [generic, claude, codex]
|
|
40
|
+
notes: >
|
|
41
|
+
Zero-token. Requires a manual physical cash count entered as
|
|
42
|
+
expected_on_hand before each run — this doesn't track cash movement
|
|
43
|
+
automatically.
|