Skip to content

fix(skills): show the new skill after creating it#5949

Merged
waleedlatif1 merged 4 commits into
stagingfrom
worktree-skill-create-redirect
Jul 25, 2026
Merged

fix(skills): show the new skill after creating it#5949
waleedlatif1 merged 4 commits into
stagingfrom
worktree-skill-create-redirect

Conversation

@waleedlatif1

Copy link
Copy Markdown
Collaborator

Summary

  • Creating a skill left you on /skills/new with the header still reading "New skill", the fields still filled, and no confirmation. The redirect was there but the unsaved-changes guard undid it: isDirty was derived from createSkill.isSuccess, so on success the guard's effect fired history.back() to pop its sentinel entry and cancelled the router.push that had just run.
  • The guard now exposes release() to retire itself for the rest of the mount; the create page calls it before navigating with replace, so the sentinel entry is consumed instead of stacked and Back doesn't land on a stale empty form.
  • Added a success toast on create — and on save, which was silent (create loud / save silent in the same feature was the only clearly wrong outcome).

Rest is from a cleanup pass over the same surfaces:

  • useCreateSkill resolves the created row, so the page reads created.id instead of re-deriving it by name from the response list.
  • Seed the list cache with the upsert's authoritative list verbatim — POST /api/skills returns the same listSkillsForUser payload as GET, and the old id-merge preserved the previous ordering, briefly rendering the new skill at the bottom of a createdAt desc list.
  • Detail page treats placeholder data as loading. useSkills is workspace-scoped with keepPreviousData, so a workspace switch served another workspace's list as success-with-no-match and flashed "Skill not found." Matches the existing integration-skills-section.tsx precedent.
  • Credential-detail drafts seed on id change instead of in a value-keyed effect, so a background refetch can't clobber an in-progress edit (or silently reset isDirty and pop the sentinel mid-edit).
  • Toast on delete failure, which was fully silent.
  • Delete navigates with replace and retires the guard, so Back can't return to the deleted skill's URL.

Type of Change

  • Bug fix

Testing

Typecheck, bun run lint:check (19/19 packages), check:api-validation, and the skills test suite (22 tests) all pass. Not yet clicked through in a browser — the fix is reasoned from the history/effect ordering, so worth a manual pass on the deploy preview.

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

The create page navigated to the new skill's detail route, but the
unsaved-changes guard immediately undid it: `isDirty` was derived from
`createSkill.isSuccess`, so on success the guard's effect fired
`history.back()` to pop its sentinel entry and cancelled the navigation
that had just run. The header stayed on "New skill" with the fields
intact, and nothing confirmed the save.

The guard now exposes `release()` to retire itself for the rest of the
mount, and the create page calls it before navigating with `replace` so
the sentinel entry is consumed rather than stacked.

Also from a cleanup pass over the same surfaces:
- `useCreateSkill` resolves the created row, so the page reads `created.id`
  instead of re-deriving it from the response list
- seed the list cache with the upsert's authoritative list verbatim; the
  id-merge kept the previous ordering and appended the new skill last
- treat placeholder data as loading in the detail page, which could
  otherwise flash "Skill not found." on a workspace switch
- seed credential-detail drafts on id change rather than in a value-keyed
  effect, so a background refetch can't clobber an in-progress edit
- toast on save and on delete failure, which were both silent
@vercel

vercel Bot commented Jul 25, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Jul 25, 2026 2:12am

Request Review

@cursor

cursor Bot commented Jul 25, 2026

Copy link
Copy Markdown

PR Summary

Low Risk
Client-side navigation, React Query cache, and UI polish in workspace skills/settings; no auth or server contract changes beyond using existing upsert responses.

Overview
Fixes skill create staying on /skills/new after success: the unsaved-changes guard no longer treats mutation success as “clean” (which popped the history sentinel and cancelled the pending redirect). useUnsavedChangesGuard now exposes release() / rearm() so callers can retire the trap before intentional navigation; create and delete use router.replace after release() so the seeded back entry is consumed instead of fighting navigation.

Skills UX and data: success toasts on create/save; delete failures surface a toast. useCreateSkill returns the created row and seeds the list cache from the upsert’s authoritative ordering (fixes brief wrong sort). Detail and custom-tools lists treat isPlaceholderData as loading to avoid false “not found” when switching workspaces. Optimistic delete keeps a loading state until navigation completes; failed delete rearms the guard.

UI cleanup: resource tile chrome is shared via RESOURCE_TILE_BASE / RESOURCE_TILE_FILL; SettingsResourceRow owns trailing flex-shrink-0 so list callers can drop redundant shrink classes. Minor skills list typography alignment; useUpdateSkill no longer invalidates the editors roster on content-only updates.

Reviewed by Cursor Bugbot for commit 6aad77e. Configure here.

@greptile-apps

greptile-apps Bot commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes skill creation and deletion navigation while improving related cache, loading, notification, draft, and shared resource-row behavior.

  • Adds release/rearm lifecycle controls to the unsaved-changes guard and uses replacement navigation after creating or deleting a skill.
  • Returns the newly created skill from the create mutation and refreshes the skills cache using the server-provided ordering.
  • Treats workspace-scoped placeholder data as loading and keeps optimistic deletion transitions in a loading state.
  • Adds success and failure notifications for skill mutations.
  • Consolidates resource-tile styling and trailing-action sizing across workspace settings surfaces.

Confidence Score: 5/5

The PR appears safe to merge with no eligible blocking failures identified in this follow-up review.

No blocking failures remain.

Important Files Changed

Filename Overview
apps/sim/app/workspace/[workspaceId]/components/credential-detail/hooks/use-unsaved-changes-guard.ts Adds explicit release and rearm controls while tracking whether the history sentinel is consumed during a released interval.
apps/sim/app/workspace/[workspaceId]/skills/new/skill-create.tsx Navigates directly to the returned created skill after releasing the guard and displays a success notification.
apps/sim/app/workspace/[workspaceId]/skills/[skillId]/skill-detail.tsx Improves workspace-transition loading, save/delete notifications, and optimistic-delete navigation handling.
apps/sim/hooks/queries/skills.ts Returns the created skill from the mutation, preserves authoritative response ordering, and narrows member-query invalidation.
apps/sim/app/workspace/[workspaceId]/settings/components/settings-resource-row/settings-resource-row.tsx Reuses shared tile styling and centrally prevents trailing controls from shrinking.

Sequence Diagram

sequenceDiagram
  participant User
  participant Page as Skill page
  participant Guard as Unsaved-change guard
  participant API as Skills API
  participant Router
  User->>Page: Create or delete skill
  Page->>Guard: release()
  Page->>API: Run mutation
  alt Mutation succeeds
    API-->>Page: Updated skill data
    Page->>Router: replace(destination)
  else Mutation fails after early release
    API-->>Page: Error
    Page->>Guard: rearm() when applicable
  end
Loading

Reviews (4): Last reviewed commit: "fix(skills): track a sentinel consumed w..." | Re-trigger Greptile

Comment thread apps/sim/app/workspace/[workspaceId]/skills/new/skill-create.tsx
…lifecycle

Follow-ups from an audit of the skills and custom tools surfaces.

Custom tools row, now matching the skills row exactly:
- the trailing arrow could be squeezed by a long description; the shared row
  owns `flex-shrink-0` for its trailing slot, so the five callers that
  hand-rolled it (and the two that forgot) all get it
- drop a redundant `cursor-pointer` — Tailwind v3's preflight already sets it
  on `button`
- the tile chrome was defined twice, in ResourceTile and again in
  SettingsResourceRow, despite ResourceTile's doc claiming to be the single
  source. Both now share RESOURCE_TILE_BASE/RESOURCE_TILE_FILL, and
  ResourceTile's redundant wrapper div is gone
- skills' row uses the text-sm/text-caption tokens instead of literal pixels;
  the added gap-[1px] offsets the 21px->20px line-height so the row stays 39px

Guard and cache correctness:
- the delete path released the guard after the await, but the delete is
  optimistic — the row leaves the cache first, so the form went clean
  mid-flight and popped the sentinel before the release landed. Release up
  front and rearm if the request fails
- hold the loading frame across the whole optimistic delete instead of
  flashing "Skill not found." on the way out
- custom tools had the same placeholder-data bug just fixed in skill detail,
  and worse: a deep-linked id could resolve against the workspace just left
- keep cached rows the create response omits, so a concurrent create isn't
  dropped until the refetch lands
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

release() suppressed the unload warning and the browser Back trap, but the
in-app back link still keyed only on isDirty — so the Skills chip could open
the unsaved-changes modal after a successful create, while the drafts were
still populated and the navigation was already in flight.
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

release() intentionally leaves the seeded history entry in place, but it also
drops the popstate listener — so Back during the released window (an optimistic
delete's round-trip) consumed that entry with nothing to record it. hasSentinelRef
stayed true, and a failed delete's rearm() then skipped re-seeding, leaving the
surface with no Back confirm despite unsaved edits.

The released branch now keeps a bookkeeping-only popstate listener that clears
the ref, so rearm() seeds a fresh entry when the old one is gone.
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 6aad77e. Configure here.

@waleedlatif1
waleedlatif1 merged commit 2272d4c into staging Jul 25, 2026
20 checks passed
@waleedlatif1
waleedlatif1 deleted the worktree-skill-create-redirect branch July 25, 2026 02:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant