octoperf-scheduling — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited octoperf-scheduling (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
OctoPerf can fire a load-test scenario on a schedule — either once at a future moment, or recurrently via a cron expression. Every fire consumes credits exactly like a manual `run_scenario`, so a daily cron drains the subscription every day until you pause or delete it.
weekly soak test, regression run after a release tag, etc.
it, change its cadence, delete it.
OctoPerf's cron parser is UnixCronTrigger — 5 fields, no seconds, evaluated in UTC on the server. Quartz expressions like 0 0 3 * * ? (6 fields) are rejected with an opaque HTTP 400.
The five fields are:
minute hour day-of-month month day-of-week
0-59 0-23 1-31 1-12 0-7 (0 and 7 are Sunday)Use * for "any value". Comma lists (1,15), ranges (1-5) and step values (*/15) work. Day-of-week uses Unix conventions (1=Monday in the documented examples).
A user saying "every night at midnight" almost never means UTC. You have to convert their local time to UTC before computing the expression. Examples for Europe/Paris:
| User's local cadence | DST (CEST = UTC+2) | Winter (CET = UTC+1) |
|---|---|---|
| Daily at midnight Paris | 0 22 * * * | 0 23 * * * |
| Daily at 09:00 Paris | 0 7 * * * | 0 8 * * * |
| Weekdays at 08:30 Paris | 30 6 * * 1-5 | 30 7 * * 1-5 |
| Monthly on the 1st at 03:00 Paris | 0 1 1 * * | 0 2 1 * * |
Daylight Saving Time is a real concern: a daily Paris cron set in summer will fire one hour off in winter (and vice versa). The user either accepts that drift, or you advise picking a less DST-sensitive slot (e.g. anchor on UTC and tell them when it fires in local time).
When in doubt, ask the user which fixed-UTC slot they want, or use a single-fire schedule_scenario_once with an ISO-8601 offset which is unambiguous.
Before schedule_scenario_*, call get_scenario_matching_plans on the scenario. If it returns an empty list, the scheduled run will fail at startup every single fire until someone notices and disables the job.
mcp__octoperf__get_scenario_matching_plans(scenarioId)Empty result → flag to the user, run list_active_subscriptions to explain which cap is binding, do not schedule.
A scheduled cron is also more dangerous than a manual run_scenario because:
before producing samples (list_bench_docker_logs)
schedule_scenario_once) — for "run X at this specificmoment". Takes an ISO-8601 datetime with timezone offset (2026-06-15T03:00:00+02:00) — unambiguous, no timezone math.
schedule_scenario_cron) — for "every N days /hours / Monday morning / etc.". Requires the Unix 5-field UTC cron.
For one-shot:
appropriate offset for that wall-clock date (mind DST).
2026-05-15T18:00:00+02:00.For recurring:
transitions.
mcp__octoperf__get_scenario_matching_plans(scenarioId) # MUST be non-empty
mcp__octoperf__schedule_scenario_once(scenarioId, runAt, name)
# or
mcp__octoperf__schedule_scenario_cron(scenarioId, expression, name)Always pass an explicit name — empty names make the scheduler view in the OctoPerf UI hard to read.
Both tools return nextRun (epoch-ms). Render it back to the user in their local time so they can sanity-check ("nextRun = 2026-05-15T00:00 Paris ✓" — not "1778796000000"). If it lands on the wrong instant, the UTC conversion is off — fix the cron and re-schedule.
mcp__octoperf__list_scheduled_jobs_by_project(projectId)
mcp__octoperf__enable_scheduled_job(jobId) # re-arms credit-consuming runs
mcp__octoperf__disable_scheduled_job(jobId) # safe pause, reversible
mcp__octoperf__delete_scheduled_job(jobId) # destructive — prefer disableThe list returns every job in the project — including the disabled ones. Group by enabled when reporting to the user.
A scheduled fire that errored before producing samples won't show up in list_bench_reports_by_project like a real run. To audit:
list_scheduled_jobs_by_project(projectId) → check each job'snextRun — if a daily cron's nextRun is in the past, something is off (the trigger may be misconfigured).
(list_bench_reports_by_project filtered on the scenario's id) and check their state via get_bench_result. ERROR-state runs without metrics = the fire happened but the scenario didn't start.
octoperf-scenario-diagnosisstep 0 ("did the run even start?") — list_bench_docker_logs on the bench result id is the next step.
delete_scheduled_job is irreversible. Use disable_scheduled_job and keep the config around.octoperf-scenario-diagnosis — when a scheduled run produced bad metrics or errored before sampling.~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.