- Provide a professional, modern, simple CLI for manual operation.
- Use the same pipeline code path as scheduled runs.
- Support safe re-runs (replace only after success) and deletions.
- Make storage browsing and stats discoverable and friendly.
- Document the CLI so it is easy for humans and LLMs to use.
- Notifications only when
--notifyis passed. - Single intended time selector for running:
--at <ISO|YYYY-MM-DD>. - Replace behavior: run new job first, replace old run only on success.
- Invocation:
pnpm reporter(not a global binary). - Rerun failures do not write a failed manifest; preserve existing run.
Command layout (single entrypoint with subcommands):
-
reporter run- Runs a job for the slot resolved from
--at. --job <id>(required unless--all)--at <date|datetime>(required)--notify(optional)--json(machine output)
- Runs a job for the slot resolved from
-
reporter rerun- Same as
run, but replaces an existing slot after success. --job <id>+--at <date|datetime>(required)--notify(optional)--json
- Same as
-
reporter delete- Deletes a specific slot and updates indexes.
--job <id>+--at <date|datetime>(required)--yes(required to execute)--json
-
reporter listreporter list ownersreporter list jobs --owner <owner> --owner-type <user|org>reporter list runs --owner <owner> --owner-type <user|org> --job <id> --window <start..end>--jsonfor machine output
-
reporter stats- Aggregated stats for a window.
--owner <owner> --owner-type <user|org> [--job <id>] --window <start..end>--json
--atresolves the slot using the job schedule and configured timezone.- Accepts:
- Full ISO (with timezone) for precise selection.
- Date-only (
YYYY-MM-DD) interpreted in the configured timezone.
- Implementation:
resolveSlotForAt(job, at, timeZone)which derives the correct slot key/window using existing slot helpers.
Create a small runner API so CLI and scheduled runs share code cleanly:
-
src/runner/run-job.tsrunJobForSlot(job, slot, { config, storage, notify }) -> RunResultRunResultincludesstatus,durationMs,slotKey,outputUri,manifestKey.- Sets
notifyso webhooks/Slack run only when requested.
-
src/runner/slots.tsresolveSlotForAt(job, at, timeZone)- Centralized date parsing and slot resolution.
-
src/storage-index.ts- Read and write helpers for:
jobs.json{YYYY-MM}.jsonmonthly indexeslatest.json
- Recalc latest after deletions or reruns.
- Read and write helpers for:
-
src/storage-transaction.ts- Wraps
StorageClientto allow "buffered writes with read-through". - Commit writes only after successful run.
- On replace: remove stale keys under
{prefix}/{ownerType}/{owner}/{jobId}/{slotKey}/that are not in the new output set.
- Wraps
-
src/cli.ts- CLI entrypoint (uses a command parser library like
commander). - Maps subcommands to runner/index helpers.
- CLI entrypoint (uses a command parser library like
Update src/index.ts to delegate to runJobForSlot, so scheduled runs and CLI share logic.
Use storage indexes instead of full bucket scans:
- Owners:
- List keys under
${prefix}/_index/and findjobs.json.
- List keys under
- Jobs:
- Read
jobs.jsonto list jobs for an owner.
- Read
- Runs:
- Read monthly indexes for a time window (using
loadIndexItemsForRange). - Optionally fetch
manifest.jsonfor details (--detailsor on-demand).
- Read monthly indexes for a time window (using
Optional: allow --prefix override to target non-default storage roots (low effort).
Compute windowed stats using index items (fast) and optional manifest fetches (detail):
- Base stats from index items:
- Run count, success/fail, total output bytes, slot coverage.
- Totals from
metricswhen present (commits, prs, issues, repos, etc).
- Optional detailed stats:
- Pull
durationMsfrom manifest for averages/p95 (or add to summary/index). - Pull LLM usage (tokens/model) if available.
- Pull
If performance is a concern, add durationMs to summary/index payload in a later step.
- All destructive actions require
--yes. rerunnever deletes old output unless the new run succeeds.--jsonoutput for automation; pretty tables by default for humans.- Clear error messages when job/owner is missing or
--atis invalid.
Add docs/CLI.md:
- Quickstart examples
- Command reference
- Output examples (
--jsonvs human) - Replace/delete safety rules
- Timezone and
--atsemantics
Update README.md to link docs/CLI.md and include a minimal CLI example.
- ✅ Runner/slot refactor and
--notifygating. - ✅ CLI skeleton with
run,rerun,delete. - ✅ Listing commands wired to
_indexdata. - ✅ Stats command for window aggregation.
- ✅ Documentation and examples.
- Confirm output format for list/stats (table vs JSON default).
- Decide whether to add
--detailsto pull manifests for durations.