Recipes

PG1 self-operating service: scheduled reports, findings-to-tasks, low-risk auto-merge with rollback

Discovered from README cross-links · today

Software & DevOpsWork & Operations

Agent runs its own ops: daily/weekly reports, tasks, guarded auto-merge

What they did

PG1 (project-gifted1/pg1-ai-agent) extended its existing autonomy policy, opportunity scan, autonomous tick, lab, watches/push and approval cards rather than building a parallel system. New code lives in `lib/operator/` and hooks into those. They added a daily 07:15 UTC cron (`api/operator/daily.mjs`) covering real usage vs. the prior day and 7-day average, payments in the last 24h (402s, paid, settled, on-chain via `lib/usageVerify.mjs`), errors by fault, production deploys and state, what PG1 did on its own, next tasks, waiting approvals, and a leading 'Production is pinned' section when a rollback or non-live merge has pinned production. The weekly Monday 07:30 UTC opportunity-scan cron was moved from 06:41 and extended with weekly requests, unserved demand split real/probe, payment funnel, discovery health, experiments and proposals. Reports are stored, shown as chat cards, pushed to devices, saved as PDFs, and readable via `/report today` and `/report week`; unreadable sources are named 'not read', never estimated. Each finding becomes one deduplicated task (fix, improve, new, listing, pricing) with counts as evidence, routed to lab experiments, PRs, listing prep or pricing checks. They added `code:merge_low_risk`: FREE only with PG1_AUTONOMY=on and the switch on, and only for lab PRs from fix/improve tasks that pass required CI checks on the head SHA, a whole-diff read (paged to 300 files, every file patched), no weakened or deleted tests, no config/env/SQL changes, no protected paths, no MCP contract change, under 300 changed lines, a passed promotion gate, and a 3/day one-at-a-time cap. Merges are watched 60 minutes and rolled back on failed deploy, not Ready, or >50% error-rate/p95 regression, followed by a revert PR and push. After a rollback production is pinned, auto-merge pauses, and `/report resume` only resumes once production serves the newest Ready deploy. Approvals appear in the report with Approve/Decline via `task_decide` or `/report approve|decline`, refuse any actor but operator, and expire after 7 days.

How it went

Shipped as a PR (not merged yet) on top of #403 with conflicts resolved by keeping both sides. `tests/operator.test.mjs` has 82 tests covering reports, findings, every disqualifying rule, stuck checks, rollback and pinning, approvals and the migration; lab and autonomy tests pass 115/115 and browser tests for the report cards pass. CI on 248db61 passed every job except `npm test` (one failure from the test file reaching `supabase.test`, fixed in e9b4ad8) and the always-red Cloudflare Workers Builds app check; not yet re-run on the latest commits.

Worth knowing

Explicitly not to be merged yet. The migration is additive but databases that already ran 20261113120000 need the `pr_opened_at` alter line run once by hand. Auto-merge needs `PG1_AUTONOMY=on`, `PG1_VERCEL_PROJECT_ID` (or exposed `VERCEL_PROJECT_ID`) and a `GITHUB_TOKEN` with contents and pull-requests write; `PG1_PAID_CALL_WORST_CASE_USD` and `PG1_PRODUCTION_ALIAS` are optional. The Cloudflare Workers Builds app check is always red and is deliberately ignored. CI has not been re-run on the latest commits, and the pin check depends on the Vercel aliases API.

Wiring

Order: (1) apply the additive migration `supabase/migrations/20261113120000_pg1_operator.sql` creating `pg1_operator_reports` and `pg1_operator_tasks` (RLS on, no policies) with `pr_opened_at`, widening `pg1_autonomous_actions.status` for `expired`, and run the `alter table ... add column if not exists pr_opened_at` line once on databases that already ran the earlier file; (2) set env: `PG1_AUTONOMY=on`, `PG1_VERCEL_PROJECT_ID` (or exposed `VERCEL_PROJECT_ID`), `GITHUB_TOKEN` with contents + pull-requests write, optional `PG1_PAID_CALL_WORST_CASE_USD` and `PG1_PRODUCTION_ALIAS` (default `pg1-ai-agent.vercel.app`), reusing existing `VERCEL_TOKEN`, `VERCEL_TEAM_ID`, VAPID keys and lab secrets; (3) add the daily cron `api/operator/daily.mjs` at 07:15 UTC and move the opportunity-scan cron to Mondays 07:30 UTC with the extended sections; (4) wire findings into `pg1_operator_tasks` deduplicated by key, feeding the lab, listing prep and pricing checks; (5) implement `qualifyPr` and `code:merge_low_risk` in `lib/operator/`, reading CI via the GitHub API on the head SHA (only `npm test` and `browser tests` count), paging the diff to 300 files, and enforcing the protected-path, test-weakening, config and size rules; (6) add the pre-merge alias check via `GET /v4/aliases/{alias}`, the 60-minute watch, and rollback via `POST /v1/projects/{id}/rollback/{prevDeployment}` plus revert PR and push; (7) route approvals through `task_decide` (operator session only) or `/report approve|decline <id>`, running the item's APPROVAL action with `approved: true`; (8) add `/report today`, `/report week` and `/report resume`, and run `tests/operator.test.mjs` plus the browser report-card tests.

Try it yourself

Read the PG1 operator design in this repo (lib/operator/, api/operator/daily.mjs, the weekly opportunity-scan cron, lib/autonomy.mjs, lib/lab/, lib/usageVerify.mjs, supabase/migrations/20261113120000_pg1_operator.sql, tests/operator.test.mjs). Then, without creating a parallel system, do three things: (1) add a daily 07:15 UTC operator report cron that reads real usage vs. prior day and 7-day average, 24h payments, errors by fault, deploy state, autonomy log, next tasks and waiting approvals, names any unreadable source as 'not read' instead of estimating, and stores/pushes/PDFs the report with `/report today` and `/report week`; (2) turn each finding into one deduplicated task (fix, improve, new, listing, pricing) with counts as evidence, routed to lab experiments, PRs, listing prep or the 1.5x pricing check; (3) implement `code:merge_low_risk` gated on PG1_AUTONOMY=on plus the switch, qualifying only lab fix/improve PRs that pass required CI on the head SHA, have a fully-read diff (paged to 300 files, every file patched), add no weakened or deleted tests, touch no config/env/SQL/protected paths or MCP contract, stay under 300 changed lines, pass the promotion gate, and respect a 3/day one-at-a-time cap. Add a 60-minute post-merge watch with rollback on failed deploy, not Ready, or >50% error-rate/p95 regression, a revert PR and push, production pinning that pauses auto-merge, and `/report resume` that only resumes once production serves the newest Ready deploy. Add Approve/Decline in the report via `task_decide` (operator only) with 7-day expiry, and write tests for every disqualifying rule, stuck checks, rollback and pinning, approvals and the migration.

Source

Tools in this stack