Conversation
3c4cc6d removed --max-turns so a multi-file resolution could finish. 9c01436 re-applied the workflow from a pre-3c4cc6d7 buffer and brought the cap back, so every run with more than a couple of conflicts died on "Reached maximum number of turns (12)". timeout-minutes: 20 remains the outer bound. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The workflow file was added independently on main and staging, so the merge base has no version of the path and git reports add/add. Any edit to it on main therefore conflicts regardless of staging's content, and the old guard turned that into a hard failure -- the workflow deadlocked on every change to itself. CI definitions belong to main in a main->staging flow, so conflicts under .github/ are now settled with `git checkout --theirs` before Claude runs. Verify asserts each .github/ path the merge touched is byte-identical to main's copy, per-path rather than as a blanket diff, since staging carries its own non-conflicting CODEOWNERS and build.yml. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
… with no heartbeat details Replaces the v1.1.1 timing window with the timeout failure's lastHeartbeatDetails.
…torage milestones
…ut-retry feat(orchestrator): post workflow v1.1.2 retries on heartbeat timeout with no heartbeat details
…ns, onboarding improvements)
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_560d7ab4-db93-4ee9-9119-76e558fb7fd7) |
There was a problem hiding this comment.
Code Review
This pull request introduces onboarding enhancements, including support for third-party MCP client icons, and upgrades the background workflow to version 1.1.2 with automatic retry capabilities on heartbeat timeouts. Key feedback points out a potential runtime TypeError due to unsafe access of the optional integration property on the post object, and an unused poked variable in the workflow. Additionally, there is a potential crash when using btoa with non-ASCII characters, and a UX issue where the local CLI installation section is unnecessarily displayed for remote clients like Claude and ChatGPT.
| if (!post) { | ||
| await changeState(postId, 'ERROR', 'No Post'); | ||
| return; | ||
| } |
There was a problem hiding this comment.
The post object returned from getPostsList has an optional integration property (integration?: Integration). Accessing properties on it directly (e.g., post.integration.token or post.integration.organizationId) or passing it to activities without checking if it is defined can throw a TypeError at runtime. In Temporal, a TypeError inside a workflow will fail the workflow task and block execution. Adding a guard right after retrieving the post ensures robust and defensive execution.
if (!post) {
await changeState(postId, 'ERROR', 'No Post');
return;
}
if (!post.integration) {
await changeState(postId, 'ERROR', 'No Integration');
return;
}| let poked = false; | ||
| setHandler(poke, () => { | ||
| poked = true; | ||
| }); |
There was a problem hiding this comment.
The poked variable is declared and set to true inside the poke signal handler, but it is never read or used anywhere else in the workflow. If the signal is intended to wake up the workflow from its scheduling sleep, that logic is currently missing (since await sleep(...) is not interrupted by signals unless raced). If it is not needed, the unused variable and handler should be removed to improve maintainability.
| return `cursor://anysphere.cursor-deeplink/mcp/install?name=postiz&config=${btoa( | ||
| JSON.stringify(server) | ||
| )}`; |
There was a problem hiding this comment.
The standard btoa function throws a DOMException if the input string contains any characters outside of the Latin1 range (0x00-0xff). If mcpBase or apiKey contains non-ASCII characters (e.g., in self-hosted IDN domains or custom keys), this will crash the onboarding modal. Safely encoding the string to UTF-8 before calling btoa prevents this issue.
| return `cursor://anysphere.cursor-deeplink/mcp/install?name=postiz&config=${btoa( | |
| JSON.stringify(server) | |
| )}`; | |
| return "cursor://anysphere.cursor-deeplink/mcp/install?name=postiz&config=" + btoa( | |
| unescape(encodeURIComponent(JSON.stringify(server))) | |
| ); |
| ) : ( | ||
| <> | ||
| {connectorSection} | ||
| <div className="grid grid-cols-2 gap-[16px]"> | ||
| {mcpSection} | ||
| {cliSection} | ||
| </div> | ||
| </> | ||
| )} |
There was a problem hiding this comment.
The onboarding modal displays the local CLI installation section (cliSection) side-by-side with the MCP configuration for all clients except apiTab and chatOnly clients. This is incorrect and confusing for remote/hosted clients like Claude and ChatGPT, which do not use or require the local CLI. Hiding the CLI section and making the MCP section full-width for these remote clients improves the onboarding UX.
) : (
<>
{connectorSection}
<div className={clsx(agent === 'Claude' || agent === 'ChatGPT' ? "flex flex-col" : "grid grid-cols-2", "gap-[16px]")}>
{mcpSection}
{agent !== 'Claude' && agent !== 'ChatGPT' && cliSection}
</div>
</>
)
What kind of change does this PR introduce?
Feature & Ecosystem Sync: Backend, Orchestrator, Frontend. Merges upstream Postiz updates (Post Workflow v1.1.2, MCP Client Icons, Onboarding improvements) and updates Crove Post roadmap.
Why was this change needed?
To bring the latest upstream Postiz stability enhancements (workflow retry resilience on heartbeat timeout and expanded MCP agent support) into
mainand deploy to the live production environment.Technical Details & Scope
apps/orchestrator: Addedpost.workflow.v1.1.2.tsto retry publishing activities on heartbeat timeouts with zero heartbeat details.apps/frontend:mcp.client.icons.tsx.onboarding.modal.tsxand public API components.docs:ROADMAP.mdwith Crove OS visual modernization and media architecture milestones.CHANGELOG.md.staging-conflicts.ymlso it only runs on upstreamgitroomhq/postiz-app.Verification & Testing
pnpm --filter ./apps/backend run build(PASS).pnpm --filter ./apps/orchestrator run build(PASS).pnpm --filter @crove/sso test(31/31 passed).pnpm dlx tsx scripts/branding-guard.ts(100% passed).QA
post.crove.com/auth/api/healthreturns200 OKChecklist:
pnpm run build).Note
Medium Risk
New
postWorkflowV112changes core publish/retry behavior for all queued posts; incorrect retry logic could duplicate or strand posts. The staging-conflicts workflow can push tostagingwhen enabled on the upstream repo.Overview
Syncs upstream Postiz changes into Crove Post: scheduled publishing now uses Temporal
postWorkflowV112(replacing v1.1.1) with smarter handling of heartbeat timeouts—retries when no heartbeat was ever received, otherwise treats outcomes as unknown to avoid duplicate posts. Developers & onboarding gain a third wizard step (Connect Agents), shared MCP helpers, oauth vs API key auth, more clients (OpenClaw, Hermes, NanoClaw, Grok Bot, etc.),McpClientIcon, and Cursor one-click install.Settings > Developers MCP UI is aligned with the same client list and auth model. Docs update
CHANGELOG.mdand expandROADMAP.md(Crove OS UI, R2, AI). CI addsstaging-conflicts.yml: periodic probe ofmain→stagingmerges, Claude-assisted resolution, verification, and push—gated togitroomhq/postiz-apponly so forks do not run it.Reviewed by Cursor Bugbot for commit d838d21. Configure here.