Files
PaperClipAI/ui
DottaandPaperclip 7fd05e1354 fix(skills): keep initial file editor drafts clean (#19241)
## 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 master e8163fc860.

**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 head 8336145: 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>
2026-11-05 07:58:34 -06:00
..
…

@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.