## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - People inspect and edit skill files from the Skills library. > - The Markdown editor receives the body without YAML frontmatter. > - The skill page compared that body with the entire saved file. > - Opening Edit therefore showed unsaved changes before the person typed. > - This pull request uses the same saved body for initialization, comparison and Discard. > - Clean files stay clean, while real edits retain the existing save path. ## Linked Issues or Issue Description **What happened?** Open an editable SKILL.md with YAML frontmatter in the Skills library. Select Files, then Edit. The page immediately shows Unsaved changes without input. The draft contains only the body, while the dirty check compares it with the full file. **Expected behavior** Opening Edit leaves the file clean and Save disabled. Real input enables Save. Discard restores the original body. Saving an edit keeps the existing frontmatter. **Steps to reproduce** 1. Open a managed skill whose SKILL.md has YAML frontmatter and a Markdown body. 2. Select Files, then Edit. 3. Make no editor input. 4. Observe the dirty indicator and Save state. **Paperclip version or commit** Reproduced locally on mastere8163fc860. **Deployment mode** Rendered local page tests for both Skills-library interface variants. API data and the rich-editor boundary are mocked. Fixed live-browser acceptance remains unverified. Related: #13915 suppresses initial rich-editor normalization, and #9356 improves Skill Studio edit tracking. This defect occurs in the Skills-library page before any editor change event. ## What Changed - Compare the draft with the same body used by Markdown initialization. - Restore that body on Discard, without inserting frontmatter into the body editor. - Disable Save when the file is clean. - Cover both page variants through actual page hydration and the Edit button. - Preserve real edits, exact fixture frontmatter, custom metadata and file-selection behavior. ## Verification - Before the fix, both rendered page variants fail after Edit shows Unsaved changes without an editor change event. - The same regressions pass after the four-line production correction. - 137 focused tests pass across CompanySkills, MarkdownEditor and company-skill-routes. - The page regression checks genuine input, Discard and re-entry, an explicit metadata-preserving save, and switching away from an unsaved prior-file draft without another save. - UI typecheck and production build pass. Token gates and diff checks pass. - The first typecheck lacked ignored generated Storybook catalog files. The existing generator supplied them; the failed prerequisite attempt remains recorded. - Independent local Sol review passed the candidate. - Full-workspace LOCAL typecheck, tests and build were not run. - Hosted CI passes on head8336145: typecheck, build, selected general tests, all eight E2E shards and aggregate gates. Four scope-based checks are skipped: Storybook visual, Storybook deployment, Runner matrix and serialized server suites. This is affected-scope coverage. - Greptile reviewed the exact head with a 5/5 score and no actionable findings. - Paperclip native review was filtered by the configured Draft and Ready event policy. This is not a completed native review or a native 5/5 result. The review route uses independent local Sol review and hosted Greptile. Repository-required checks and reviews still govern merge. - No fixed live-browser, deployed behavior or canonical-file mutation is claimed. ## Risks The change affects the Skills-library page baseline in both existing interface variants. It keeps the existing frontmatter merge and file-write API. Rich-editor normalization, Skill Studio, settings, permissions and selection lifecycle remain unchanged. The tests isolate the page baseline with a controlled editor boundary; they do not prove a live rich-editor or server write journey. ## Model Used OpenAI gpt-6.1-sol through Codex, with reasoning, source inspection, code execution and local tests. The runtime did not expose context-window size. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge Co-authored-by: Paperclip <paperclip@paperclipai.com>
@paperclipai/ui
Published static assets for the Paperclip board UI.
What gets published
The npm package contains the production build under dist/. It does not ship the UI source tree or workspace-only dependencies.
Storybook
Storybook config, stories, and fixtures live under ui/storybook/.
pnpm --filter @paperclipai/ui storybook
pnpm --filter @paperclipai/ui build-storybook
Typical use
Install the package, then serve or copy the built files from node_modules/@paperclipai/ui/dist.
Editor dependency identity
Keep the root and workspace overrides for @codemirror/state,
@codemirror/view, and @lezer/common aligned. CodeMirror requires shared
extension identity, while Lezer parsers and syntax highlighters require shared
NodeProp IDs. Multiple Lezer copies can crash code-block highlighting with
tags is not iterable. src/lib/codemirror-single-instance.test.ts checks the
installed dependency graph and highlights sample code through the editor's real
language dependencies. GitHub Actions owns regeneration of pnpm-lock.yaml.