v0.7.20: perf, ui improvements, fable 5, tables row size bump, blogs#5337
Conversation
…5321) * fix(custom-tool): restore modal body scroll so Save stays reachable The Edit/Create Agent Tool modal clipped its footer (Save/Update) and could not scroll with long code or schema content. Root cause: #4354 migrated the modal to ChipModal and changed the body from a scroll region (flex-1 overflow-y-auto) to flex-none overflow-visible so the hand-positioned EnvVar/Tag autocompletes could spill past it. That removed the scroll region, so tall content grew the body past the modal's max-h-[84vh] cap and the overflow-hidden surface clipped the footer. Restore ChipModalBody as the scroll region (its documented behavior) and switch the EnvVar/Tag dropdowns to portaled inputRef caret-anchoring, matching the canonical Function-block editor, so they anchor to the caret in a portal and are never clipped by the scroll boundary. * fix(custom-tool): keep dropdown anchors content-relative on body scroll Review follow-up. The autocomplete popovers already portal their menus (never clipped by the body's scroll boundary), so the fix is only to restore the body as the scroll region. Reverting the dropdowns to their content-relative absolute anchors keeps them glued to the caret while the body scrolls; the caret-viewport inputRef anchoring used fixed viewport coordinates that only refreshed on edits, detaching the menu on scroll.
- workflow-mcp: move tool-edit state seeding from a derive effect into the Edit event handler - admin: drop 2 inert useMemo (page math) and 1 unused useCallback - inbox + teammates: migrate filter/search view-state from useState to nuqs URL params (shareable, debounced writes) - team roster: memoize O(workspaces x members) grouping so keystroke search stays cheap at scale - remove dead code (unused props/locals: currentUserEmail, setOrgName, isLoadingWorkflows, isTeam)
…5322) * fix(connectors): allow self-hosted private DB hosts via opt-in flag Database/connector tools rejected any host resolving to a private/reserved/ loopback IP, blocking the common self-hosted topology where the DB is reached by a Docker/K8s/Swarm service name. Add an opt-in ALLOW_PRIVATE_DATABASE_HOSTS flag that bypasses the private-host block in validateDatabaseHost while still resolving and pinning DNS. Blocked on the hosted platform regardless of the env var, mirroring DISABLE_AUTH. Fixes #4319 * fix(connectors): pin postgres IP in all ssl modes; strip IPv6 brackets Address review on #5322: - validateDatabaseHost now strips surrounding IPv6 brackets before the localhost/private-IP checks and DNS lookup, so a bracketed loopback like [::1] is classified correctly instead of failing as unresolvable. - PostgreSQL connector always connects to the validated, pinned IP (removed the ssl='preferred' carve-out that passed the original hostname and let the driver re-resolve during connection). Matches the MySQL/MongoDB pin pattern. - Add postgres connector pinning tests and bracketed-IPv6 host tests. * fix(connectors): rename flag to isPrivateDatabaseHostsAllowed; trim comment - Rename env-flag const to satisfy the env-flags 'is' prefix CI check (env var ALLOW_PRIVATE_DATABASE_HOSTS is unchanged). - Tighten the postgres pinning comment to a single line.
…nnet-5 (#5328) Claude Sonnet 5 rejects the temperature parameter with a 400 ("`temperature` is deprecated for this model"), verified against the live Anthropic API. The model entry exposed temperature: { min: 0, max: 1 }, so supportsTemperature() returned true and the Anthropic request builder sent temperature whenever thinking was disabled, breaking those runs. Remove the capability (matching Opus 4.7/4.8, which omit it for the same reason) so temperature is never sent for Sonnet 5. Add a supportsTemperature regression assertion.
* improvement(settings): react-doctor perf & correctness pass - combine multi-pass array iterations into single passes (api-keys, credential-sets, secrets-manager, team-management) - cache/hoist Intl formatters to module scope (billing); hoist pure functions and inline-default constants - stabilize react-query array fallbacks so memos stop recomputing while loading (api-keys, byok, workflow-mcp) - fix create-workflow-mcp modal reset via render-phase prevOpen compare instead of a state-adjusting effect - accessibility: aria-labels on real inputs, aria-hidden on autofill decoys, native <button> for clickable rows - immutable in-place sort where the array is already a fresh copy * fix(settings): render non-clickable inbox rows as div, not disabled button Addresses review: a native disabled <button> can inherit browser disabled styling (dimmed text / lower contrast) on non-navigable task rows. Render an interactive <button> only when the row is clickable; otherwise a plain <div> with identical layout — preserving the semantic-button a11y win without the disabled-state visual regression.
…face (#5326) * improvement(landing): react-doctor health pass across the landing surface - shared JsonLd server component with HTML-safe serialization (replaces 32 inline dangerouslySetInnerHTML JSON-LD sites; structured-data output semantically identical, XSS hardened) - state/effect fixes: derive-instead-of-sync, phase state machines, useSyncExternalStore for media query, handler-only state to refs - structural splits for one-component-per-file and non-component export isolation - mechanical: combined iterations, hoisted Intl formatters/static values, immutable sorts, stable keys, a11y labels, focus rings, SVG precision - ES2023 lib for apps/sim to allow toSorted/toReversed * fix(landing): harden auth-modal async open (dismiss race + disabled-signup redirect) - guard the pending provider-status fetch with openRequestedRef so a late resolve can't reopen the modal or re-fire the opened event after dismiss - open synchronously (loader) when status is still loading so the click stays responsive - route to /login instead of /signup when registration is disabled and no modal providers are available * fix(landing): reset demo step index when the preview auto-cycle restarts - reactive isDesktop can re-run the demo effect on a 1024px resize; reset demoIndexRef to 0 so applyDemoStep(step 0) and scheduleNextStep read the same step, instead of replaying from a stale index and skipping beats - clarify why the chat reveal's previous-value ref is safe here (timer-driven, no concurrent-interruption boundary) * fix(landing): single-shot auth open, stable connector keys, exact prompt-row lookup - auth-modal: consume openRequestedRef on resolve so a queued double-click (or the shared mount prefetch) can't run openWithStatus twice (no duplicate auth_modal_opened / redundant setView) - landing-preview-knowledge: key connector icons by a stable slug instead of a component name that can be mangled/emptied under minification - workflow-data getEditorPrompt: single ordered pass preserves the original find() first-match-in-order semantics (Map lookup had preferred 'Prompt' over an earlier 'System Prompt') * style(landing): convert added inline comments to TSDoc-style
…chat bundle (#5331) * improvement(chat): code-split resource preview panel out of initial /chat bundle Lazy-load the MothershipView resource-preview panel (file-viewer, rich-markdown, CSV/PDF stack) via React.lazy + local Suspense so it is not in the initial /chat bundle; it only renders once a chat has messages. Remove its now-dead barrel re-export so the split takes effect (this app has no sideEffects:false, so a leftover barrel edge drags the heavy module back into the initial chunk). Also a small behavior-preserving perf pass on the input surface: - toSorted (non-mutating) instead of spread+sort in use-skill-auto-mention - Map first-match lookup instead of .find()-in-loop in prompt-editor Document the code-split/barrel gotcha in .claude/rules/sim-imports.md. * fix(chat): drop unsafe toSorted, keep code-split + Map lookup toSorted (ES2023) is not polyfilled by SWC and crashes iOS15/Safari<16 in client bundles, so revert use-skill-auto-mention to the non-mutating [...arr].sort() it had. The code-split of MothershipView and the first-match Map lookup in prompt-editor are unaffected. Tighten the sim-imports code-split note to state webpack *can* retain the barrel edge (removing the dead re-export is the guaranteed fix).
* improvement(tables): react-doctor safe performance pass Apply high-confidence, behavior-preserving perf fixes surfaced by react-doctor on the tables module: - Lazy-init the import-status ref so it stops allocating and discarding a fresh Map on every render (rerender-lazy-ref-init). - expandToDisplayColumns: build an outputs-by-column-name Map once per workflow group instead of Array.find() per column (js-index-maps). - Sort the tables list with toSorted() instead of [...list].sort() (js-tosorted-immutable; ES2023 lib is enabled for apps/sim). - Hoist the static TITLE_BY_MODE map and the pure editor wheel handler to module scope so they are not rebuilt each render. Left the effect/selection refactors (state-synced-to-prop, effect chains) untouched: those effects react to async-loaded rows and are not the copy-a-prop-into-state anti-pattern; refactoring them needs live grid verification. Barrel-import findings are false positives against the repo's mandated barrel-import convention. * improvement(tables): preserve find() first-match semantics + document perf idioms - expandToDisplayColumns: build the outputs-by-column-name index with an explicit first-write-wins loop so it is provably identical to the prior Array.find() on the (schema-precluded) duplicate-columnName case, not last-wins as new Map(entries) would be. - Add .claude/rules/sim-react-performance.md capturing the behavior- preserving render-perf idioms applied here (lazy object refs, module- scope hoisting, Map/Set pre-indexing, immutable array methods with the ES2022/ES2023 lib caveat, local-barrel false-positive note), and point to it from CLAUDE.md. * fix(tables): revert toSorted to spread-sort for universal browser support Array.prototype.toSorted is ES2023 runtime; SWC does not polyfill it and the default browserslist still includes browsers without it (iOS 15 Safari), so the tables page would crash there. [...result].sort() is non-mutating (sorts a copy, never touches the React Query cache array) and works everywhere; the perf delta is negligible. Correct the sim-react-performance rule doc to reflect that tsconfig lib only affects type-checking, not runtime availability. * refactor(tables): tidy lazy ref init and align perf-rule cross-reference - use-workspace-imports: lazy-init the status Map at its point of use in the effect ((ref.current ??= new Map())) instead of mutating the ref during render with a separate in-effect fallback. The ref is only read in the effect, so this removes the render-phase write and the dead '?? new Map()' branch while keeping the identical persistent Map. - CLAUDE.md: fix the render-performance pointer so it matches the rule doc — toSorted/toReversed are unsafe on client render paths (SWC does not polyfill prototype methods), not merely an ES2022/ES2023 lib note.
…#5330) * improvement(files): react-doctor performance pass on the files module * fix(files): use spread-sort not toSorted in client (Safari<16/iOS15 crash) SWC does not polyfill Array.prototype.toSorted and the repo sets no core-js/browserslist target, so it throws on Safari <16 / iOS 15. Revert the two client-side toSorted calls to [...arr].sort() and correct the harness guidance in sim-components.md accordingly.
…ase module (#5332) * improvement(knowledge): react-doctor perf pass across the knowledge base module * improvement(knowledge): drop stable mutate fn from useCallback deps * docs(rules): tighten sim-react-performance mutation + toSorted wording
Re-add claude-fable-5 (Anthropic's most capable widely released model), not marked recommended. Verified against live Anthropic API + docs: - Pricing $10/$50 per MTok, $1 cached input (cache-read); 1M context; 128k max output; GA 2026-06-09 - Adaptive thinking only (always on, cannot be disabled) — routed via supportsAdaptiveThinking; manual budget_tokens/temperature are rejected with 400 - effort levels low/medium/high/xhigh/max (default high) - nativeStructuredOutputs confirmed supported (live output_format json_schema call returned 200), matching same-generation siblings (Sonnet 5, Opus 4.8)
… + no-render-in-render caveat (#5333) Two recurring pitfalls surfaced by the /w react-doctor pass, verified against react.dev: - sim-hooks.md: adjusting state on a prop transition uses the React-canonical useState prev-value tracker (NOT a useRef — React forbids reading/writing ref.current during render; the react-hooks 'refs' lint flags it, and useState is concurrent-safe). The tracker's initial value decides mount behavior (sentinel vs current value) — a mis-seed silently drops the mount action. The existing useRef variant is noted as discouraged for new code. - sim-components.md: no-render-in-render is a false positive for a helper called inline (reconciled by position, no remount); extract only when mechanical. Refs: react.dev useState 'Storing information from previous renders'; useRef 'Do not write or read ref.current during rendering'; react-hooks 'refs' lint.
…ion (#5335) * fix(demo): unblock Cal.com booking embed and align work-email validation - Exclude /demo from cross-origin isolation headers (COEP credentialless / COOP same-origin) that degraded the third-party Cal.com booking iframe, mirroring the existing Google Drive Picker exclusion; the booker no longer loads under a Storage-Access handshake that often never finished - Pin the Cal embed theme/layout in the inline config to fix a dark-on-light theme race; keep cal('ui') to UI-only settings - Gate the demo form's Continue on the same work-email rule the server enforces via a shared isFreeEmailDomain helper, bundle-isolated in lib/messaging/email/free-email.ts so it doesn't bloat other email bundles - Trim redundant comments in the demo components * fix(demo): match /demo subroutes in permissive COEP rule Align the permissive-headers positive match with the strict-COEP negative lookahead so any future /demo subroute still receives the permissive COEP/COOP policy instead of falling through to no headers. * fix(demo): use demo.* in permissive COEP rule (valid route source) The demo(/.*)? form introduced a nested capturing group, which Next's path-to-regexp route-source parser rejects ('Capturing groups are not allowed'), failing the build. demo.* mirrors the strict-rule lookahead's demo prefix without a nested group, matching the existing w/.* style.
|
Too many files changed for review. ( Bypass the limit by tagging |
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
PR SummaryMedium Risk Overview Engineering guidelines gain a dedicated CI & migrations: PII / data retention support: the Presidio service adds Public interfaces drop forced Landing polish: shared Config: Reviewed by Cursor Bugbot for commit dcc7c0c. Bugbot is set up for automated code reviews on this repo. Configure here. |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
There are 2 total unresolved issues (including 1 from previous review).
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 4421512. Configure here.
…res, unsubscribe, invite) with emcn components (#5336) * fix(interfaces): pin deployed chat + resume to light mode, emcn-only components * fix(interfaces): review feedback — formErrors dep in field renderer, keep overlay tint on attachment remove * improvement(interfaces): chat header uses the platform SimWordmark instead of the svg asset * fix(interfaces): light mode for file-share gates, unsubscribe, and invite surfaces
…5340) toSorted/toReversed require Safari 16+/iOS 16+ and Next.js/SWC does not polyfill prototype methods (vercel/next.js#58421 closed unmerged), so #5326 broke sorting on the models page and landing preview for Safari 15/iOS 15 with a runtime TypeError. Revert the 6 call sites to [...arr].sort()/[...arr].reverse() (immutable, universally supported, matches the existing codebase idiom) and drop the ES2023 tsconfig lib override that only existed to type-check them.
…, restore scroll on back-nav (#5342) * fix(integrations): repair corrupt icons, backfill missing block metas, restore scroll on back-nav - Restore 7 brand icons (Google, Outlook, MongoDB, Postgres, OpenRouter, Groq, Cerebras) whose SVG path data was corrupted by a past bulk reformat, flooding the integrations page console with <path> parse errors; add a check:icon-paths CI gate that validates every icon d attribute (operand counts + arc flags). - Backfill BlockMeta (tags/url/templates/skills) for postgresql, mysql, ssh, sftp, smtp — previously catalog integrations with empty detail pages; add an integration meta-coverage CI check so every catalog block must have a meta. - Add scroll-position restoration for the integrations index/detail inner scroll containers so browser Back returns to where you were. - Remove the error digest pill from the shared workspace ErrorShell (kept in logs, dropped from UI). * fix(integrations): make scroll restoration robust — value-based echo detection + Back/Forward-only gate Addresses review: replace the racy programmatic-scroll flag with value comparison (a restore's echo equals lastApplied and is ignored, so a stuck flag can never drop the first user scroll or overwrite the saved target), and gate restoration on popstate history traversals so fresh push navigations open at the top instead of jumping mid-list. TSDoc-only comments. * fix(ci): attribute icon-path errors for export-const icons too Greptile review: iconNameAt only matched 'export function', so a malformed path inside an 'export const XxxIcon = (...)' arrow-function icon would be misattributed to the preceding function-declared icon. Match both forms (mirrors check-bare-icons indexIconBodies).
* feat(logs): add Troubleshoot in Chat button for errored runs
Errored log runs now surface a "Troubleshoot in Chat" action in the log
details panel. It tags the failed run as a logs context (executionId) and
auto-sends a message to Chat asking Sim to investigate and fix the error,
porting the old copilot "Fix in Chat" behavior to mothership and adding
run-ID tagging.
Cross-route handoff rides a one-shot MothershipHandoffStorage consumed once
on the home surface mount, so the tagged run + prompt survive the navigation
from Logs to Chat and the agent receives the full run error via the resolved
logs context.
* fix(logs): deliver troubleshoot to a mounted chat + harden handoff
Review follow-ups:
- Same-route case (Cursor): LogDetailsContent is also embedded in the Chat
resource panel, where router.push('/home') doesn't remount Home, so the
mount-only handoff consume never fired. Generalize the existing
sendMothershipMessage event to carry contexts and be cancelable: deliver
straight to a mounted chat when one claims it, and only persist + navigate
when none is listening.
- Corrupted-entry tombstone (Greptile): consume now clears whenever any entry
exists, so a malformed/expired handoff can't linger across future mounts.
- Silent store failure (Greptile): only navigate when the handoff actually
stored, so a failed write never strands the user on an empty chat.
* docs(logs): convert inline comments to TSDoc on declarations
* style(logs): match Troubleshoot button icon gap to View Snapshot sibling
* improvement(logs): use Chip for log-detail action buttons
Aligns the log-details panel's labeled action buttons (View Snapshot,
Troubleshoot in Chat) with the settings design language by swapping the
emcn Button for the canonical Chip pill. variant='primary' preserves the
prior filled emphasis; leftIcon keeps the icons canonical.
* fix(chat): only consume troubleshoot handoff on the new-chat surface
Gate the mount-time handoff consume on `!chatId` so an existing
`/chat/[chatId]` mount can't claim a pending handoff if navigation races —
a handoff always targets a fresh chat.
* fix(logs): hover only the interactive Run ID row in log details
The detail-card rows all hovered to --surface-2, but the card itself is
--surface-2, so the hover was a no-op in light mode and only showed in dark.
It also implied clickability on static readout rows. Now only the clickable
Run ID row hovers, using the canonical --surface-active token; static rows
carry no hover.
* improvement(logs): use emcn Badge for the version pill
Replaces the hand-rolled version span with the canonical Badge
(variant='green' size='md', pixel-identical tokens), so all three detail
badges (Level, Trigger, Version) render through the same component.
… detail page (#5345) Root cause (confirmed via staging server logs, digest 783665031): the [block] page.tsx is a server component whose Suspense fallback rendered <ChipLink leftIcon={ArrowLeft}> — passing the lucide icon (a function) across the server->client boundary, which React rejects ("Functions cannot be passed directly to Client Components"). This surfaced as the integrations error boundary / "Failed to load integrations" on soft navigation to a detail page. Move the fallback into a client component so the icon never crosses the boundary.
* fix(chat): scope troubleshoot handoff to its workspace MothershipHandoffStorage now records the target workspaceId and only the matching workspace consumes (and clears) it; a different workspace leaves it untouched for its owner. Prevents a workspace-A handoff from firing in workspace B, where A's executionId can't resolve and the run context is dropped. * test(chat): cover legacy no-workspaceId handoff tombstoning
SecretReveal (the post-submit redacted state) used bespoke h-9/rounded-md/px-2.5 chrome with an absolutely-positioned copy button, instead of the canonical chip-field chrome (h-[30px]/rounded-lg/px-2) that SecretInput (the pre-submit state) uses. That mismatch made the credential-paste widget visibly resize right after saving. Rebuilt SecretReveal on the same chipFieldSurfaceClass tokens as ChipInput, with the copy button as an inline trailing adornment.
* feat(blog): add five AI agent articles Add how-to-create-an-ai-agent, ai-agent-vs-chatbot, ai-agents-vs-rpa, ai-agent-ideas, and best-zapier-alternatives posts. * fix(blog): correct ai-agent-ideas pronoun and complete zapier TL;DR Fix 'everyone' -> 'every idea' in ai-agent-ideas intro; add the four missing tools (Power Automate, Pipedream, Relay.app, Integrately) to the best-zapier-alternatives TL;DR so it lists all 10. * fix(blog): remove HIPAA compliance claims We are not HIPAA compliant; drop the claim from ai-agents-vs-rpa and best-zapier-alternatives, keeping the SOC2 claim. * feat(blog): add cover images for new posts, refresh older post covers - Add cover.jpg for the 5 new AI agent blog posts - Replace existing cover art for enterprise, mothership, v0-5, multiplayer, executor, series-a, and openai-vs-n8n-vs-sim - Standardize openai-vs-n8n-vs-sim's og image to cover.jpg (was workflow.png) - Update ogImage frontmatter paths to match * fix(blog): move new post dates closer to today Shift the 5 new AI agent posts from June 23-27 to June 27 - July 1, keeping the same order and 1-day spacing, ending on today's date. * fix(blog): use current Sim terminology instead of legacy Mothership/Copilot names Per the constitution language rules, Sim's own natural-language agent surface is "Chat" and the agent you talk to is "Sim" — not "Mothership" or "Copilot" (those are prior internal names, still used correctly in the historical announcement posts but not for new content). Leaves references to Zapier's and Microsoft's own "Copilot" products as-is since those name real third-party features.
…tputs) (#5272) * feat(data-retention): granular PII redaction stages (input + block outputs) * fix(data-retention): propagate block-output redaction into child workflows * fix(data-retention): close block-output redaction gaps on streaming + resume * fix(data-retention): drain+mask streamed output, resolve PII policy unconditionally (no fail-open) * test(testing): support leftJoin().where().limit() in shared db mock * fix(data-retention): mask agent/Pi memory writes under block-output redaction * fix(data-retention): guard partial PII stages in GET normalize * fix(data-retention): mask seeded memory messages under block-output redaction * fix(guardrails): fail closed on misaligned Presidio batch responses * fix(data-retention): enabled stage with no entity types redacts all (no fail-open) * fix(data-retention): reject enabled stage with no entity types; empty = off everywhere * docs(data-retention): note resume remask covers inline values only * fix(data-retention): scrub offloaded large-value refs from logs when block-output redaction is off * fix(data-retention): hydrate, mask, and re-store large-value refs in logs (preserve redacted content) * fix(data-retention): always apply logs policy to large-value refs when logs stage is on * perf(data-retention): drop redaction byte ceiling, parallelize chunks (env-tunable), remove request timeouts, sync large-value walk * feat(data-retention): gate granular PII stages behind pii-granular-redaction flag - New pii-granular-redaction feature flag (fallback PII_GRANULAR_REDACTION), layered on pii-redaction, gating the execution-altering input + block-output stages - Route returns piiGranularRedactionEnabled and rejects enabling granular stages when off - UI shows only the Logs stage tab unless the flag is on; clamps active stage - Drop the per-search Select all toggle; add a Deselect all action to the PII section header * docs(pii): describe Presidio as a standalone service, not a sidecar Presidio now runs as its own ECS service (and, in Helm, its own Deployment + Service) reached over the network via PII_URL — not a sidecar in the app task. Update README, code comments, env docs, Dockerfiles, and the Helm chart docs to match, and note the deploy requirement that PII_URL must be reachable. * fix(data-retention): re-mask offloaded large-value refs on resume + don't lock out granular saves - Resume/run-from-block restore now hydrates → masks → re-stores large-value refs in restored blockStates (not just inline strings), so a value offloaded before the block-output stage was enabled can't warm raw PII into downstream blocks. Fails fast. - pii-large-values: add onFailure mode (throw on the execution path, scrub for logs) and redactLargeValueRefsInValue for arbitrary (non-RedactablePayload) values - Granular flag gate now rejects only NEW off→on granular enablement, so orgs that already configured granular stages can still save retention settings when the flag is off
…pt (#5343) * ci(trigger): auto-deploy Trigger.dev tasks to dev-sim on dev pushes Add a deploy-trigger-dev job that runs `trigger.dev deploy --env preview --branch dev-sim` on pushes to the dev branch, replacing the manual step. Gated after migrate-dev for the same reason as build-dev: the new task code runs against the dev DB, so the schema must be pushed first. Uses Trigger.dev's remote build (no --local-build), so the runner needs no Docker/buildx. Requires a TRIGGER_ACCESS_TOKEN repo secret. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015orsjbLX34FPFGujSK3AQK * ci(trigger): source TRIGGER_PROJECT_ID from repo secret Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015orsjbLX34FPFGujSK3AQK * ci(trigger): fail fast when Trigger.dev secrets are unset Guard the deploy step so a missing TRIGGER_ACCESS_TOKEN or TRIGGER_PROJECT_ID exits with a clear message instead of a cryptic trigger.dev CLI error, matching the DATABASE_URL guard in migrations.yml. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015orsjbLX34FPFGujSK3AQK * ci(migrations): fail dev db:push on interactive prompt or error drizzle-kit push prompts interactively for ambiguous renames (--force only covers data-loss). In CI there's no TTY, so the prompt reads EOF and drizzle can exit 0 without applying — the job goes green while the schema change was silently skipped. Close stdin, reject prompt markers, and require a success marker so an unresolved rename or failed statement fails the job. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015orsjbLX34FPFGujSK3AQK * ci(migrations): fail dev db:push when drizzle-kit hits a TTY prompt drizzle-kit push needs a TTY to resolve ambiguous renames; in CI it throws "Interactive prompts require a TTY terminal" but still exits 0, so the job went green without applying the schema (e.g. run 28415609570). Fail on that explicit error. Keys on drizzle's own stable message rather than fuzzy prompt text, and a real non-zero exit still fails via set -e. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015orsjbLX34FPFGujSK3AQK * ci(trigger): scope the access token secret as DEV_TRIGGER_ACCESS_TOKEN The PAT is only used by the dev deploy job, so prefix it DEV_ to match the repo's dev-scoped secret convention. TRIGGER_PROJECT_ID stays unprefixed — it's the shared project (same one prod uses); dev-sim is a preview branch within it, not a separate project. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015orsjbLX34FPFGujSK3AQK * Adjust warning error * ci: align build-dev checkout to v6 to match the other jobs build-dev was the only job still pinning actions/checkout to the v4 hash; every other job uses v6. Non-functional consistency fix. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015orsjbLX34FPFGujSK3AQK --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- reuse the shared Cta component (same "Build your first agent today" band used on the homepage) at the end of the blog listing
Two concrete regressions from the earlier Chip conversion (#5341): - Both chips used variant='primary' (the solid inverse-fill treatment), the heaviest chrome in the design system, reserved for a single standout action per context (Save, Upgrade, Add key) — never a peer among several row actions. Two solid pills stacked in a narrow side panel read as oversized. Switched both to the bare (default) chip, matching every analogous row action in Settings. - The Version badge was size='md' while its siblings (Level, Trigger) are size='sm' — an inconsistency. Aligned to 'sm'. Also folded the floating 'Troubleshoot in Chat' chip into the Details card as its own row (matching 'Snapshot' exactly) instead of leaving it orphaned below Workflow Output — every row in the card now shares one shape (label left, trailing content right), consistent top to bottom.

Uh oh!
There was an error while loading. Please reload this page.