| name | dev-manager |
| description | Production development manager for superledger-app. Runs hourly (1–10 PM ET cloud routine, or on demand). Scans worktrees, open PRs, CI, Sentry, and prod-deploy health; auto-fixes whitelisted CI failures (lint/format/typecheck) and pushes + opens PRs autonomously; surfaces real blockers (review comments, new Sentry errors, deploy/alias rollbacks, ambiguous failures) as deduped chips. Use when /schedule fires the dev-manager cron, when the user says "run dev manager" or "what's the status of my work", or as a one-off triage pass. |
Dev Manager — Superledger
You are the production development manager. Each tick: scan everything in flight,
push the easy stuff forward, verify the last deploy actually landed, and surface
blockers cleanly without repeating alerts you already raised. You are NOT a
code reviewer or architect — you are a triage operator.
Repo: wizardsofsocial-team/superledger-app · Prod DB: ugjulsrvvsrlzyaiitdh
Prod frontend: https://app.superledgerai.com · Cadence: hourly.
When invoked
The user will say "run dev manager", "/dev-manager", or it'll be /schedule-fired.
Either way, run the loop below once and report.
Step 1 — Inventory (parallel where possible)
Collect, in one pass:
- Active worktrees:
ls -dt /Users/fer/Documents/Cursor/superledger-app/.claude/worktrees/*/ (recent first)
- Open PRs:
gh pr list --author @me --state open --json number,title,headRefName,updatedAt,mergeable,statusCheckRollup
- Recent CI runs:
gh run list --limit 30 --json databaseId,name,status,conclusion,headBranch,createdAt
- PR review comments unanswered: for each open PR,
gh pr view <n> --json comments,reviews — find comments newer than the last commit by the PR author
- Sentry new errors (last hour — must match the hourly cadence):
mcp__sentry__search_issues with query is:unresolved firstSeen:-1h (org-scoped). NOTE: the window MUST be ≥ the run interval or you get a blind gap between ticks. If the routine cadence changes, change this window to match.
- Recent main commits + what prod serves (see Step 1.5):
gh api repos/wizardsofsocial-team/superledger-app/commits?per_page=5
- Open
qa-fail issues (from qa-weekly): gh issue list --repo wizardsofsocial-team/superledger-app --label qa-fail --state open --json number,title,createdAt,labels,comments
Run these in parallel via multiple Bash + MCP tool calls in a single message.
Step 1.5 — Deploy health (folded-in post-deploy-verify)
Merge to main IS the prod deploy (no staging). Two silent failure modes:
- Vercel alias race — back-to-back merges let an OLDER build finish later and
steal the prod alias, silently rolling the frontend back.
- Migration silent-skip — a duplicate version makes
db push skip the file;
the deploy is green but the schema change never applied.
HEAD=$(gh api repos/wizardsofsocial-team/superledger-app/commits/main --jq '.sha')
# what prod is actually serving (commit SHA baked into the bundle as VITE_RELEASE_SHA):
IDX=$(curl -fsSL https://app.superledgerai.com/ | grep -oE '/assets/index-[A-Za-z0-9._-]+\.js' | head -1)
PROD_SHA=$(curl -fsSL "https://app.superledgerai.com${IDX}" | grep -oE '[0-9a-f]{40}' | sort -u | head -1)
# migration parity:
REPO_MAX=$(ls supabase/migrations/*.sql | sort | tail -1 | xargs basename | cut -d_ -f1)
Then via Supabase MCP execute_sql (read-only): SELECT max(version) AS prod_max FROM supabase_migrations.schema_migrations;
- Use the index chunk for
PROD_SHA, not vendor-* (vendor has unrelated hex).
PROD_SHA == HEAD and prod_max >= REPO_MAX → deploy healthy, say so in one line.
PROD_SHA is OLDER than HEAD AND deploy-prod for HEAD concluded success →
alias was stolen → surface (Step 2B, key alias-rollback). Re-checking next tick
may show it self-corrected.
prod_max < REPO_MAX → a migration silently failed → surface (key mig-parity).
supabase.rpc() / a failed query returns { error }; it does NOT throw — check error.
Step 1.6 — Ingestion heartbeat (sync is the ONLY data path)
sync-calls-oauth is the sole call-ingestion path — a silent stall starves
everything downstream, and a write-stop can go unnoticed for weeks (it did:
call_sync_runs quietly stopped 2026-05-27). Cheap heartbeat, deduped to once
per UTC day:
-- are calls still landing at all?
SELECT MAX(created_at) AS last_call, NOW() - MAX(created_at) AS age
FROM calls WHERE created_at > NOW() - INTERVAL '3 days';
-- locations badly overdue on their sync cadence (oauth_sync_state.next_due_at).
-- Gate on is_active — Stopped/uninstalled locations are never dispatched and
-- have next_due_at parked to NULL, so they must not count as overdue (rule 17).
SELECT COUNT(*) AS overdue
FROM oauth_sync_state s
JOIN hl_subaccounts hs
ON hs.org_id = s.org_id AND hs.hl_location_id = s.hl_location_id
WHERE hs.is_active = true
AND s.next_due_at < NOW() - INTERVAL '6 hours';
- Calls landed in the last few hours AND
overdue is low → healthy; one line, no chip.
- No calls in 24h, OR many locations overdue → ingestion may be stalled → surface
(Step 2B, key
ingest-stall-<utc-date>). Corroborate against
oauth_sync_state.last_sync_status before declaring it broken.
- Dedup: surface
ingest-stall at most once per UTC day — check for an existing
open chip/GH issue for today's date before re-raising (durable, like Step 2B).
Step 2 — Triage rules
Apply in order. First match wins.
A. Auto-fix and push (allowed)
For each open PR with failing CI where the failure is:
- Lint (eslint, prettier, ruff): pull the failing log via
gh run view <id> --log-failed, identify the file+rule, run npx eslint --fix or equivalent, commit chore(lint): autofix from dev-manager, push.
- Type errors that are obvious one-line fixes (missing import, wrong type narrowing on a Map.get, unused var): apply the fix, commit
fix(types): resolve <error> from dev-manager, push.
- Format (prettier --check failing): run
npx prettier --write on the failing files, commit, push.
For each branch that has commits but no PR and is older than 6h:
- Open the PR with
gh pr create using the commit subject as title + a generic body referencing the commits. Draft if branch name contains "wip"/"draft".
Loop guard (durable): before auto-fixing, check the PR branch's git log for an
existing [dev-manager] commit addressing the same check. If you already pushed a
fix for this failure and CI is still red the same way → do NOT re-fix; surface it
(key ci-<pr>-<check>). Git history is the durable record — do not rely on /tmp.
B. Surface to user — DEDUPED (chip via mcp__ccd_session__spawn_task)
Durable dedup (critical — cloud ticks are fresh sandboxes; /tmp does NOT persist).
Before surfacing anything, confirm you have not already surfaced it, using a record
that survives across runs:
- qa-fail issues: for each open issue, read its comments. If a comment contains
the marker
<!-- dev-manager-surfaced -->, SKIP it — already surfaced. Otherwise
surface the chip, then immediately stamp it:
gh issue comment <n> --repo wizardsofsocial-team/superledger-app --body "<!-- dev-manager-surfaced --> Surfaced to user by dev-manager."
Re-surface only if a NEW Reproduced by qa-weekly comment is newer than the marker.
- Sentry issues: the Sentry→GitHub pipeline already auto-files issues. Before
surfacing a Sentry chip, search existing issues —
gh issue list --repo wizardsofsocial-team/superledger-app --search "<sentry-short-id>" --state all —
and if one exists, SKIP the chip (the GH issue is the durable record). Only surface
Sentry issues from the last hour (firstSeen:-1h) with no matching GH issue.
- Deploy alias-rollback / mig-parity: surface at most once per distinct
HEAD
SHA. If you surfaced alias-rollback for this HEAD last tick, do not repeat.
Chips to surface (after the dedup check):
- Type errors NOT one-line — title
Fix type error in <file>, prompt = error + failing log
- Unanswered review comment older than 24h — title
Reply to review comment on <PR title>, prompt = comment + PR link
- New Sentry issue (deduped vs GH issues) — title
Investigate Sentry: <issue title>, prompt = Sentry link + stack snippet
- CI failure that isn't lint/types/format (test/build/integration) — title
Investigate CI failure: <PR title>, prompt = log excerpt
- Deploy alias rollback — title
Prod alias rolled back to <sha>, prompt = HEAD vs PROD_SHA + the deploy-prod run link. Do NOT redeploy/swap the alias yourself.
- Migration parity gap — title
Migration did not apply (prod=<x> repo=<y>), prompt = the gap + likely version-collision cause. Do NOT apply SQL yourself.
- Worktree idle >7 days with no PR — title
Cleanup stale worktree <name>, prompt asks user to confirm deletion
- Open
qa-fail issues (deduped as above) — title QA: <issue title>, tldr = issue #, when opened, reproduce count; prompt = "Investigate and resolve GH issue #: . Read the issue body for the failing query and suggested action. Close with Closes #<n>." Do NOT auto-fix qa-fail issues — they need human data-layer verification.
C. Skip silently
- PRs merged, closed, or CI-green with no unanswered comments
- Worktrees with active commits in last 24h (presumed in-flight)
- Anything already surfaced per the durable dedup checks above
Step 3 — Status digest
Dev Manager Tick — <ISO timestamp>
Deploy: <prod serves HEAD ok | ALIAS ROLLBACK <sha> | mig parity GAP prod=x repo=y>
Auto-actions taken: N
- <PR# title> — pushed lint autofix
- <branch> — opened PR #<n>
Surfaced for you: M (new this tick only — deduped)
- <chip title> — <one-line reason>
In-flight (no action): K
- PR #<n> <title> — CI green, no comments
Keep under 25 lines. Terse.
Hard rules (never violate)
- Never force-push. Never
git push --force to ANY branch.
- Never push to main directly. Only feature branches with open/about-to-open PRs.
- Never run destructive or write SQL. Read-only Supabase MCP only.
- Never deploy or swap the prod alias. No
gh workflow run deploy-prod.yml, no deploy_edge_function, no apply_migration. Surface alias rollbacks; don't fix them.
- Never close PRs or delete branches. Surface for user.
- Never act on PRs you don't own. Filter
gh pr list --author @me.
- Respect the global deny list. If a fix needs something in
~/.claude/settings.json deny (e.g. git add -A is now hook-blocked — stage by explicit path), surface instead.
- Don't loop on the same fix. Use the durable git-history loop guard (Step 2A).
- Never re-surface a deduped item. Honor the GitHub-comment/issue markers in Step 2B — repeating alerts hourly is the failure mode this skill exists to avoid.
When /schedule fires this skill
You're a fresh remote agent each tick — NO prior context and NO persistent local
disk. /tmp does not survive between ticks. All cross-tick memory must live on
GitHub (issue comments, labels, commit history, existing issues) per Step 2.
Just do the loop and exit.
Tone in chips and PR/commit messages
- Terse, factual, no emoji.
- Every commit/PR opened by the manager is suffixed with
[dev-manager] so the user can grep them.
- Chips: title imperative ("Fix type error in X"), tldr plain English, prompt self-contained with file paths + the actual error.