sweep-hq
Find orphaned CommCare HQ apps in the ACE domain and soft-delete the ones you approve. Needs a live-set from sweep-live-set.
Files1
View on GitHubSKILL.mdskills/sweep-hq/SKILL.md
GitHubsweep-hq
Find CommCare HQ applications in the ACE-owned domain (connect-ace-prod) that no current opp references and triage them. HQ apps soft-delete via doc_type mutation (restorable via HQ admin UI's "deleted applications" list); ACE drives this through the commcare_delete_app Playwright atom. Builds and multimedia remain documented gaps — no upstream delete API exists.
Inputs
- Live-set file path from
sweep-live-set. ACE_HQ_DOMAINfrom.env(defaults toconnect-ace-prod).ACE_HQ_BASE_URL(e.g.https://www.commcarehq.org).mode—recommend(default) |execute. Inrecommendthe skill is report-only: diff/score/render + return the recommended-action list; no mutations. Inexecuteit soft-deletes onlyapprovedIds. The human-confirmation gate between the two is the orchestrator's job — seeagents/sweep.md § Human-confirmation gate.approvedIds(executemode only) — the exact app ids the human approved in chat. Mutate nothing outside this set.
Products
ACE/_sweep/<timestamp>/hq-orphans.md— human-readable triage report.ACE/_sweep/<timestamp>/hq-orphans.yaml— machine-readableOrphanReport.- For approved orphan apps:
commcare_delete_app({ domain, app_id })calls.
Process
- Read the live-set via
drive_read_file. - List HQ inventory:
commcare_list_apps({ domain: ACE_HQ_DOMAIN }). Returns[{ id, name, doc_type }]for every Application in the domain (soft-deleted apps are filtered server-side). - Diff: for each app whose
idis NOT inliveSet.identifiers.commcareAppIds, mark as orphan candidate. - Score: call
scoreHqApp(item, ACE_HQ_DOMAIN)fromlib/sweep-fingerprint.ts. Returns high if the domain matches and name has Learn/Deliver/CRISPR pattern; medium for unrecognized names in the ACE domain; low for apps in a different domain (defensive — caller shouldn't normally pass these in). - Build the
OrphanReportwithsystem: 'hq'. Single Actionable section — orphan apps are soft-deletable. - Render + write
hq-orphans.mdand.yamlto the sweep folder. - Recommend — stop here in
mode: recommend. Return the structured recommended-action list (orphan apps to soft-delete — each with id, name, confidence, and the reversibility note "90-day restorable via HQ admin UI") plus the report Drive link, to the orchestrator. Perform no mutations. Do not try to prompt the human from this skill — a dispatched subagent can't reach them; the orchestrator runs the confirmation gate (seeagents/sweep.md § Human-confirmation gate).
Execute phase (mode: execute only)
Runs only when the orchestrator re-dispatches with mode: execute + approvedIds (the app ids the human approved in chat). For each approved orphan app, call commcare_delete_app({ domain: ACE_HQ_DOMAIN, app_id }). The atom POSTs to HQ's delete_app web view, which soft-deletes by mutating doc_type to <original>-Deleted and creating a DeleteApplicationRecord for restore. Mutate nothing outside approvedIds; return the per-item result.
Restoration
HQ apps are restorable for 90 days after soft-delete via the admin UI's deleted-applications list (/a/<domain>/apps/deleted/) or by calling undo_delete_app/<record_id>/. The sweep atom does NOT return the record id (the redirect response doesn't expose it), so restoration is a manual operation via the HQ web UI.
Failure modes
- Live-set path doesn't resolve: abort with "Run
sweep-live-setfirst." commcare_list_appsreturns 401 / session redirect: the existing PlaywrightSession retry handles this transparently; if the retry also fails, surface a clear "Connect/HQ session expired — run /ace:connect-login" message.commcare_delete_appreturns 403: the account lacks edit permission on the app — surface as a per-item failure, don't halt the batch.- An app is already soft-deleted (very unlikely since
commcare_list_appsfilters them out, but possible if a race occurs): the second delete returns 302 to dashboard same as the first — treat as success (no-op).
Implementation notes for agents
- HQ apps soft-delete is at
POST /a/<domain>/apps/delete_app/<app_id>/. The view is CSRF-protected (@no_conflict_require_POST+@require_can_edit_apps); thecommcare_delete_appatom handles the CSRF dance via the existing PlaywrightSession cookie jar. - API key auth is sufficient for
commcare_list_apps(CCHQ's TaskPie resource hasallow_session_auth=True, so session cookies work too — we use session cookies to keep the auth path uniform withcommcare_delete_app). - HQ builds and multimedia have no upstream delete API. They are NOT surfaced in this skill's report; the human is expected to know that builds accumulate per release-build cycle and aren't cleanable from ACE.
Related skills
sweep-live-setproduces the live-set this skill diffs against.