Skip to content

Post-#1813: send-email API for sandbox agents + delete dormant OpenClaw code in tasks #1815

Description

@sweetmantech

Follow-up to #1813 (closed — the async/scheduled chat-generation migration onto runAgentWorkflow, functionally complete and fully on prod as of 2026-06-24). The cutover works end-to-end, but it left two deferred items that this issue tracks: (1) the new sandbox agent has no way to send email, so scheduled report tasks complete without delivering anything; and (2) the now-dormant OpenClaw code still sits in the tasks repo (Phase 2 cleanup, originally gated on prod stability — that gate is now met).

Goal

After #1813, scheduled chat-generation runs entirely on POST /api/chat/runsrunAgentWorkflow with native in-sandbox tools (bash/read/write/edit/grep/glob) + a per-run ephemeral key. Two things remain before the scheduled-report use case is whole and the legacy code is gone:

  1. The sandbox agent can send email via a real Recoup API endpoint (it can't today), so report tasks actually deliver.
  2. The OpenClaw bootstrap + run-sandbox-command Trigger.dev task are deleted from tasks (nothing calls them post-cutover).

Done = a scheduled task whose prompt is "email X to Y" results in a delivered email, observable end-to-end; and grep for OpenClaw / run-sandbox-command in tasks/src returns nothing but intentional history.

PRs (updated 2026-06-25)

PR Item Base State
docs#251 POST /api/emails send-email contract (OpenAPI + SendEmailRequest/EmailResponse + nav) main ✅ merged 2026-06-25 — see Done
api#708 POST /api/emails endpoint (reuses processAndSendEmail) + chat_id rename + recipient restriction + server-side recoup_sk_-over-Bearer auth test ✅ merged 2026-06-25 + promoted to main/prod (#709) — see Done
skills#57 document POST /api/emails in recoup-platform-api-access main ✅ merged 2026-06-25 (+ doc-fix skills#59 ✅) — see Done
tasks#153 retire dead run-sandbox-command task + its exclusive code (OpenClaw Phase 2 cleanup) main ✅ merged 2026-06-25 — see Done
api#712 fix renamed global-skill refs so the sandbox agent actually installs recoup-platform-api-access (the real reason scheduled email doesn't deliver) test ✅ merged 2026-06-25 to test (6d9e74e8) + promoted to main/prod (#713) — see Done
skills#59 correct the skill to the shipped api (chat_id, recipient note, auth wording) + self-contained inline auth so the sandbox agent actually authenticates (preview test showed it reached for the unset $RECOUP_API_KEY) main ✅ merged 2026-06-25 — see Done
docs#252 make to and subject optional on POST /api/emails (to → account's own email; subject → first body line, else Message from Recoup) main ✅ merged 2026-06-25 — see Done
api#710 to and subject optional in sendEmailBodySchema — resolve account_emails when to omitted; resolveEmailSubject() defaults subject from the body (else Message from Recoup) test ✅ merged 2026-06-25 to test (18d20f7c) + promoted to main/prod (#714) — see Done
docs#253 remove POST /api/notifications (path + CreateNotificationRequest/NotificationResponse + nav + page) main ✅ merged 2026-06-25 — see Done
api#711 delete /api/notifications route + lib/notifications/* (keep processAndSendEmail) test ✅ merged 2026-06-25 to test (d9815368) + promoted to main/prod (#715)
cli#24 rename notifications command → emails (no alias) + re-point to POST /api/emails (self-send); --subject optional; --chat-idchat_id main ✅ merged + published @recoupable/cli@0.1.15 (calls /api/emails, 0 /api/notifications refs)
cli#25 harden the npm publish workflow (rebase before bump push, ref: main, workflow_dispatch) — fixed the non-fast-forward release failure main ✅ merged 2026-06-25 (its merge run published 0.1.15)
skills#60 agent-reliability fix: force bash+curl for send-email (forbid web_fetch), lock payload keys, to as array, + collapse the dual x-api-key/Bearer auth to one inline Bearer header (net deletion) main ✅ merged 2026-06-26 — measured 2/5 → 4/5, web_fetch 3/5 → 0, zero misroutes (see Done)
api#717 billing: charge 1 credit per POST /api/emails send (gate→send→deduct; recordCreditDeduction source api) test 🔄 open — 6 handler tests green
api#718 observability: Admin Telegram notification on every email sent (notifyEmailSent, best-effort) — stacked on api#717 test 🔄 open — 11 emails tests green

Follow-up bundle (the last 5 rows): two items, each merged docs → api. Item A (to + subject optional): ✅ done on proddocs#252 + api#710 (#714). Item B (delete /api/notifications): ✅ done on proddocs#253 + api#711 (promoted via api#715) + the CLI re-point cli#24 (published @recoupable/cli@0.1.15) + publish-workflow fix cli#25. The CLI was published before the prod promotion, so no caller broke.

Merge sequencing / status: Item 1's contract → endpoint chain is shipped to prod: docs#251 ✅ → api#708 ✅ (#709) → skills#57 ✅ + skills#59 ✅ (skill content now correct). Item 2 (tasks#153) ✅ merged. The skill install fix api#712 is now ✅ on prod (#713) too — so endpoint + skill content + skill install are all live. The remaining blocker is agent reliability: across three preview runs the agent loaded the skill and reached /api/emails but fumbled the call (web_fetch instead of bash+curl, to as a string, cross-env key). The endpoint+auth chain is proven (two emails delivered via the test endpoint). See the top Open — next up item.

What shipped (context) — the ephemeral-key foundation works

The per-run ephemeral key is verified working end-to-end, so Item 1 builds on solid ground (the gap is purely "no email tool", not auth):

  • The sandbox agent's shell receives the minted key as $RECOUP_ACCESS_TOKEN (a recoup_sk_… key, len 53), and it authenticates to the Recoup API: GET /api/accounts/id200, resolving to the correct accountId.
  • The key is revoked on run end (0 ephemeral:* keys linger for the account afterward).
  • Env-matching holds: a prod-minted token is valid against prod (200) and rejected by test-recoup-api.vercel.app (401) — same PRIVY_PROJECT_SECRET + DB required.
  • Evidence: recoupable/tasks#152 test comment, recoupable/api#705 test comment.

Done

  • docs#251POST /api/emails send-email contract (the docs lead the api).
    ✅ Merged 2026-06-25 to main (merge commit 4321426; docs is single-branch). First in the docs → api → skills order — this is the contract api#708 fulfills and skills#57 documents.
    Documents POST /api/emails in api-reference/openapi/accounts.json (SendEmailRequest + EmailResponse), a Send Email MDX page, and the Emails nav group. Scope evolved in review: (1) the request field was renamed room_idchat_id to match the new session/chat architecture (the footer already links to chat.recoupable.com/chat/{id}), with a hyperlink to Create Chat (POST /api/chats) so devs know where to mint one; (2) to/cc are documented as restricted to the account's own email unless a payment method is on file, linking to the credits top-up session (POST /api/credits/sessions); (3) description trimmed (KISS — dropped the Resend/third-party mention); (4) to gets minItems: 1; (5) EmailResponse { success, message, id } marked required.
    Verified: accounts.json on main at 4321426 carries POST /api/emails with chat_id (not room_id), both recipient-restriction notes, and the required EmailResponse fields; JSON validates. CodeRabbit's create.mdx openapi-frontmatter suggestion was skipped — the repo convention is "/api-reference/openapi/<spec>.json METHOD /path" (≈26 pages), which the page already follows; the bare form would break the spec ref (reason posted).

  • api#708POST /api/emails endpoint, fulfilling the docs#251 contract.
    ✅ Merged 2026-06-25 to test (merge commit 4ecca444), then promoted to main/prod via api#709 (testmain, merge commit f56e35d7); test re-synced with main afterward (27f05322).
    Adds app/api/emails (reuses processAndSendEmail → the shared send_email MCP domain fn, untouched). Contract parity with docs#251: public field chat_id (handler maps it to the internal room_id footer lookup, so the rooms-table plumbing is unchanged), and the recipient restriction — without a payment method on file, to/cc are limited to the account's own email (403), lifted by a card on file (assertRecipientsAllowed + accountHasPaymentMethod, the latter shared with ensureSongstatsPaymentMethod). Review hardening: the recipient check + auth live in validateSendEmailBody (SRP); and the server now accepts a recoup_sk_ key over Authorization: Bearer (getAuthenticatedAccountId → shared getAccountIdByApiKey), so buildRecoupExecEnv carries a single RECOUP_ACCESS_TOKEN (no client-side x-api-key routing).
    Verified end-to-end on the preview (a1a7270c, the approved commit): /api/emails → 401 (no auth) / 400 (minItems) / 200 (own email + chat_id, delivered) / 200 (shared@recoupable.com, card-on-file lifts the restriction); and a minted recoup_sk_ key returns 200 over both x-api-key and Authorization: Bearer (the new path, was 401), email send over Bearer 200, test key deleted after. 427 unit tests green; tsc 0 new errors. Results.
    Blocks nothing on the api side, but the sandbox path needs skills#57 (below): buildRecoupExecEnv no longer sets RECOUP_API_KEY, so the skill must use Authorization: Bearer $RECOUP_ACCESS_TOKEN.

  • skills#57 — document POST /api/emails in recoup-platform-api-access.
    ✅ Merged 2026-06-25 to main (recoupable/skills is single-branch). Adds the Send-email section + curl to the recoup-platform-api-access skill so the agent has the /api/emails playbook.
    Caveat — merged against the pre-merge contract; corrected by skills#59 (next). This skill only reaches the sandbox once api#712 fixes the install refs (below).

  • skills#59 — correct the skill to the shipped api + self-contained inline auth.
    ✅ Merged 2026-06-25 to main (merge commit 93396094; single-branch).
    Brings recoup-platform-api-access to parity with the shipped /api/emails: room_idchat_id, the no-card recipient restriction, and the auth note (the key authenticates over x-api-key or Authorization: Bearer). Plus the delivery-critical part, proven necessary by the 2026-06-25 api#712 preview test: a self-contained inline-auth curl. In that test the agent bypassed the top-of-skill ${AUTH[@]} helper and hand-rolled Bearer $RECOUP_API_KEY (unset in the sandbox → auth failed, no email) because each agent bash call is a fresh shell, so an AUTH set in a prior step is gone. Tech322/artist setting #59 makes the email curl resolve auth inline in one command (x-api-key when RECOUP_API_KEY set, else Bearer $RECOUP_ACCESS_TOKEN), working in both sandbox + local contexts with no cross-step state and no duplicated env var. So Tech322/artist setting #59 is not just doc accuracy — it's part of the delivery fix.
    Re-test pending: needs api#712 on the deployment so the corrected skill actually installs into the sandbox.

  • api#712 — fix the renamed global-skill refs so the sandbox actually installs the platform skills.
    ✅ Merged 2026-06-25 to test (merge commit 6d9e74e8), then promoted to main/prod via api#713.
    defaultGlobalSkillRefs.ts installed {skillName:"recoup-api"} + {skillName:"artist-workspace"} — both renamed/split in recoupable/skills, so npx skills add --skill recoup-api threw and no platform skills landed in the sandbox (broke all platform-skill loading, not just email). Now installs the real slugs (recoup-platform-api-access + recoup-platform-build-workspace + recoup-roster-{add,list,manage}-artist); recoupApiSkillPrompt.ts updated to the new names + send-email triggers. 569 tests green; tsc 0 new errors.
    Verified on the preview (results): the agent's behavior flipped from "I don't have a tool to send emails" (zero tool calls) → loads the skill and calls POST /api/emails. The skill-install fix is confirmed working. (Email delivery itself was then blocked first by a preview↔prod key-secret mismatch, then by agent-reliability fumbles — see Open — next up; the endpoint+auth chain itself is proven, with two emails delivered via the test endpoint over both headers.)

  • tasks#153 — retire the dead run-sandbox-command task (OpenClaw Phase 2 cleanup).
    ✅ Merged 2026-06-25 to main (merge commit 52b2a772; tasks is single-branch).
    Deletes src/tasks/runSandboxCommandTask.ts + the code used exclusively by it (src/schemas/sandboxSchema.ts, src/sandboxes/appendNoCommitInstruction.ts, src/sandboxes/git/syncOrgRepos.ts, + their tests) and a stale getSandboxEnv JSDoc. The broader OpenClaw subsystem stays — it's still live via the coding-agent product (the issue's earlier "dormant" guess was wrong).
    Verified: 355 tests pass; grep for the retired symbols in tasks/src is clean. Post-merge orphan audit (2026-06-25): reverse-dep-checked every helper the deleted task imported — none orphaned; each still roots in a live registered task (provisionSandboxsetup-sandbox; coding-agent; update-pr). No further dead code introduced by the deletion.

  • docs#252 — make to and subject optional on POST /api/emails (the contract for follow-up Item A).
    ✅ Merged 2026-06-25 to main (merge commit 3a025e4b; docs is single-branch).
    Drops both to and subject from SendEmailRequest.required (it now has no required fields) and documents the server-side defaults: to → the authenticated account's own email; subject → the body's first heading/line, falling back to Message from Recoup. Resend itself still needs a non-empty subject (CreateEmailBaseOptions.subject: string), so the default is resolved server-side before the Resend call. CreateNotificationRequest untouched.
    The api impl is api#710 (next Done item).

  • api#710 — make to and subject optional on POST /api/emails (the impl for follow-up Item A).
    ✅ Merged 2026-06-25 to test (merge commit 18d20f7c), then promoted to main/prod via api#714.
    sendEmailBodySchema now marks both to and subject optional. to omitted → resolves the account's own address(es) via selectAccountEmails (400 if none on file); the recipient restriction runs on the resolved recipients (own email always allowed without a card). subject omitted → resolveEmailSubject() returns the provided subject, else the body's first heading/line (text preferred, then HTML via firstMeaningfulLine/stripHtml), else Message from Recoup (120-char cap). The shared processAndSendEmail / MCP send_email / /api/notifications paths keep their own required-subject schemas — only /api/emails relaxes it.
    Verified on the preview (31d885d5, post-SRP-refactor): POST /api/emails → 200 with to+subject (regression), 200 with to omitted (delivered to the account email), 200 with subject omitted (# Pulse Report body), 200 with {} (to self, Message from Recoup), 400 on a non-array to — 4 emails delivered, Resend ids recorded. SRP: firstMeaningfulLine + stripHtml extracted to their own files (review). 159 unit tests green; tsc 0 new errors. Results.
    Unblocks cli#24 — the recoup emails re-point to /api/emails (self-send, no to) now has its dependency live on prod.

  • docs#253 — remove POST /api/notifications from the docs (the contract for follow-up Item B).
    ✅ Merged 2026-06-25 to main (merge commit b6c20e9d; docs is single-branch). The docs-first contract for deleting the superseded endpoint.
    Removes the /api/notifications path, the CreateNotificationRequest / NotificationResponse schemas, the Notifications nav group, and the reference page; re-points the cli.mdx section to /api/emails and renames it ### emails (recoup emails, per review). 128 deletions; JSON valid.
    Next for Item B: api#711 deletes the route/handlers, but cli#24 must land before/with it so recoup emails keeps working.

Done — agent reliability (the scheduled-email goal works end-to-end)

The whole pipeline is on prod (endpoint, skill content, skill install) and the agent now reliably sends the email. Path proven 2026-06-25 (real run delivered to sweetmantech@gmail.com); reliability hardened + measured 2026-06-26.

  • Make the sandbox agent reliably send the email — skills#60 ✅.
    ✅ Merged 2026-06-26 to recoupable/skills main. The agent kept fumbling the call on claude-haiku-4.5 (used web_fetch instead of bash+curl, to as a string, invented recipients/email keys — which delivered only because optional-to silently defaults to self). skills#60 (a) forces bash+curl and forbids web_fetch, (b) locks the valid keys + mandates to as a JSON array + tells it to confirm the recipient in the response, and (c) collapsed the obsolete dual x-api-key/Bearer auth into one inline Bearer header (${RECOUP_API_KEY:-$RECOUP_ACCESS_TOKEN}) — a net deletion (the server accepts a recoup_sk_ key over Bearer since api#708), removing the ${AUTH[@]} array + the cross-shell gotcha that had spawned a second, conflicting auth recipe.
    Measured (N=5 per arm, prod, → a non-self recipient shared@recoupable.com so the optional-to default can't mask a misroute): correct-send 2/5 → 4/5; web_fetch 3/5 → 0/5; payload misroutes 0; to-as-string now self-corrects to an array. Ship bar (≥4/5 + zero misroutes): met.
    Residual (optional, ~1/5): the model sometimes hardcodes Bearer $RECOUP_API_KEY (unset in the sandbox) instead of copying the ${RECOUP_API_KEY:-$RECOUP_ACCESS_TOKEN} fallback → 401, then gives up. Not a misroute. Next lever if we want >4/5: make the auth snippet more copy-exact, or use a stronger model than haiku-4.5 for the headless send. Tracked as a small follow-up, not a blocker.

Done — original send-email endpoint (superseded by the items above)

  • Add a send-email Recoup API endpoint so the sandbox agent can deliver email. ✅ The endpoint + skill + install all shipped to prod (docs#251 / api#708+Sweetmantech/myc 2200 apicronrecoupdaily pull number of new messages and new #709 / skills#57+Tech322/artist setting #59 / api#712+Sweetmantech/myc 2202 apicronrecoupdailystats daily cron at 9am et once daily #713 — all in Done). The remaining "actually delivers a scheduled email" goal now lives in the Open — next up (agent reliability) item above; this entry is kept for historical context.
    • Why: the migrated runAgentWorkflow agent has native sandbox tools but no email capability — the old getGeneralAgent path used the MCP send_email tool, which the new agent lacks. Confirmed by a diagnostic run of the "Daily Hello World Email" scheduled task: the run completed but the agent replied "I don't have an email-sending tool available in my current toolset" and made zero tool calls → no email delivered. This blocks the core scheduled-report use case (reports email their output).
    • Fix:
      1. Add a REST endpoint in api (e.g. POST /api/emails) that sends via the existing Resend integration, account-scoped from the caller's auth (validateAuthContext), so the agent can curl it with x-api-key: $RECOUP_ACCESS_TOKEN.
      2. Document it in the recoup-api skill (recoupable/skills) so the agent knows the endpoint + payload and reaches for it.
      3. Use the x-api-key header in the skill's curl examples, not Authorization: Bearer. $RECOUP_ACCESS_TOKEN carries a recoup_sk_ API key, but its env name + buildRecoupExecEnv JSDoc (api/lib/agent/tools/buildRecoupExecEnv.ts) imply a Privy JWT, and REST endpoints reject the key over Bearer (JWT path → 401) while accepting it via x-api-key (200). Either fix the docs/naming or have the skill always use x-api-key.
    • Done when: a scheduled task with a "send an email to …" prompt results in a delivered email, and the run's persisted chat shows the agent calling the new endpoint and getting a 2xx. (Bonus: the recoup-api skill no longer 401s by reaching for Bearer.)
    • PRs (merge docs → api → skills):

Open — billing

  • Charge credits for POST /api/emails.api#717 (open)
    • Price decided 2026-06-25: 1 credit ($0.01) per email. Resend's per-email cost is ≤ $0.0004 (cheapest paid tier: Pro $20 / 50,000; every tier well under $0.01), so by the "round up to $0.01 if below, else at-cost no-markup" rule → 1 credit. EMAIL_CREDIT_COST = 1.
    • Impl (matches the deep-research handler): ensureCreditsOrShortCircuit gates (402 + no send if the account can't cover it; auto-recharges via a card; does not deduct) → send → on success recordCreditDeduction({ creditsToDeduct: 1, source: "api" }) (atomic credits_usage debit + usage_events insert). Failed send (502) is not charged. Only /api/emails charges — the shared processAndSendEmail/MCP path is unchanged.
    • Original analysis below (still accurate):
    • Why: verified 2026-06-25 — the endpoint charges nothing. No credit/billing/x402/usage references anywhere in the /api/emails path (app/api/emails/route.ts, sendEmailHandler.ts, validateSendEmailBody.ts, processAndSendEmail.ts). So sends — including agent/scheduled sends — are currently free, unmetered surface area.
    • Fix: wire the existing credit primitive into the send path — deductCredits({ accountId, creditsToDeduct }) (api/lib/credits/deductCredits.ts, the same helper the research handlers use), after auth/validation and before/around processAndSendEmail. Pick a per-email credit cost, decide pre- vs post-send deduction and the insufficient-credits behavior (e.g. 402), and record it via recordCreditDeduction. Keep the MCP send_email path consistent if it should also charge.
    • Done when: a successful POST /api/emails deducts the chosen credit amount from the account; an account with insufficient credits is rejected (no send); the deduction is recorded in credits_usage / usage events.

Open — observability

  • Post an Admin Telegram notification on every email sent.api#718 (open, stacked on api#717) Decided 2026-06-25 — so the team can review the quality and frequency of emails going out (esp. agent/scheduled sends).
    • Impl: new notifyEmailSent() posts account + to/cc + subject + Resend id + timestamp to the same TELEGRAM_CHAT_ID channel as other alerts (via the existing sendMessage), best-effort (try/catch, never blocks the send), wired into sendEmailHandler after a successful send.
    • Why: sends are currently invisible — no signal when /api/emails fires. We want a per-send ping in the Admin Telegram channel to spot bad/spammy/over-frequent sends.
    • Fix: on a successful send, call the existing primitive sendMessage(text, opts) (api/lib/telegram/sendMessage.tsTELEGRAM_CHAT_ID via TELEGRAM_BOT_TOKEN; already used by the credit-spend digest). Post-send, best-effort / fire-and-forget (never fail or block the email if Telegram errors — wrap in try/catch like sendErrorNotification). Include: account id, to/cc, subject, Resend id, and a timestamp. Wire it in sendEmailHandler after processAndSendEmail succeeds; decide whether the shared processAndSendEmail (MCP send_email + any other caller) should notify too, or keep it /api/emails-only. Confirm the Admin channel id (reuse TELEGRAM_CHAT_ID or add a dedicated admin chat id).
    • Done when: each successful /api/emails send posts one message to the Admin Telegram channel with account + recipients + subject + Resend id; a Telegram failure does not affect the email response.

Done — cleanup (Item B: POST /api/notifications removed)

  • Delete the placeholder POST /api/notifications endpoint (docs + api + cli). ✅ Done on prod 2026-06-25 — docs#253 + api#711 (promoted via api#715) + cli#24 (published @recoupable/cli@0.1.15) + cli#25 (publish-workflow fix). The CLI was published before the prod promotion, so no caller 404'd. Superseded by POST /api/emails, which was built as its replacement — /api/notifications was the earlier placeholder (it emails the account's own address; /api/emails is the general send-email endpoint).
    • Why: two endpoints now cover the same ground; /api/emails is the contract we're standardizing on. Keeping /api/notifications is dead surface area.
    • Fix: remove the route + its handler/validator in api (app/api/notifications/, lib/notifications/), and the page + OpenAPI entry in docs. Keep processAndSendEmail — it's still the shared domain fn for the send_email MCP tool. Re-point anything that called /api/notifications to /api/emails.
    • 🔻 Cross-repo caller found (2026-06-25): this is 3 PRs, not 2 — the cli notifications command (cli/src/commands/notifications.ts, registered in cli/src/bin.ts) is a live caller of POST /api/notifications, and docs/cli.mdx links its reference page. So api#711 must not merge before cli#24 or recoup notifications breaks. The cli command re-points to /api/emails with no to (self-send), so it also depends on api#710 (to-optional) being live.
    • PRs (docs → api, cli before/with the api deletion):
      • docs#253 — removes the /api/notifications path + CreateNotificationRequest/NotificationResponse schemas + the Notifications nav group + the reference page (128 deletions, JSON valid); re-points the cli.mdx link to /api/emails.
      • api#711 — deletes the route + lib/notifications/* (handler, validator, both tests; 598 deletions); keeps processAndSendEmail and fixes its stale JSDoc (/api/notifications/api/emails). grep clean; lib/emails suite 126 green.
      • cli#24renames the command notificationsemails (no alias; git mv to src/commands/emails.ts, bin.ts updated), re-points to POST /api/emails, --chat-id (sends chat_id), no --to (self-send), and --subject now optional (matches api#710). 75 tests green; tsup build OK; recoup emails --help verified. ✅ Promotion gate CLEARED (2026-06-25): @recoupable/cli@0.1.15 is published and calls /api/emails (verified: 0 /api/notifications refs in the published dist/bin.cjs). The release needed a publish-workflow fix (cli#25) — the original run failed first on a stale NPM_TOKEN, then on a non-fast-forward bump push. So api#711 is now safe to promote to prod (api#715).
    • Done when: grep -r "api/notifications" api docs is clean (bar intentional history); the docs nav no longer lists it; processAndSendEmail + the MCP send_email tool still pass their suites; recoup notifications still delivers (via /api/emails).

Sequencing

Independent — but Item 1 (send-email) leads: it unblocks the user-facing scheduled-report value, while Item 2 is pure dead-code removal that can land whenever. Do Item 1 first; Item 2 any time after. The /api/notifications deletion is a tidy-up that should land before close (it depends on /api/emails being live).

Source references

  • Parent: #1813 (closed, migration complete).
  • Cutover PRs: recoupable/api#704 (re-point + ephemeral key), recoupable/api#705 (retire OpenClaw bridge), recoupable/tasks#152 (fire-and-forget cutover).
  • Key files: api/lib/skills/defaultGlobalSkillRefs.ts (the renamed-skill-ref bug — global skills installed into every sandbox), api/lib/skills/installGlobalSkills.ts (npx skills add … --skill <name>, throws on unknown name), api/lib/chat/recoupApiSkillPrompt.ts (the nudge that tells the agent which skill to load), api/lib/agent/tools/buildRecoupExecEnv.ts (token injection), tasks/src/tasks/* (OpenClaw, mostly retired by feat: upload pfp to ipfs. #153).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions