Skip to content

feat(web): add Company Brain skills settings - #1322

Merged
graphite-app[bot] merged 1 commit into
mainfrom
sreedharsreeram/taipei-v1
Aug 2, 2026
Merged

feat(web): add Company Brain skills settings#1322
graphite-app[bot] merged 1 commit into
mainfrom
sreedharsreeram/taipei-v1

Conversation

@sreedharsreeram

@sreedharsreeram sreedharsreeram commented Jul 21, 2026

Copy link
Copy Markdown
Member

Stack Context

This is the frontend half of the Company Brain Skills feature. The harness is implemented in supermemoryai/mono#2611.

What?

Add Skills settings with separate Org-wide and Personal sections, Markdown upload autofill, scoped creation and editing, approval controls, and server-driven permissions.

Why?

Members need a focused way to manage their private playbooks while admins create and approve organization-wide guidance.

Related


Session Details

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jul 21, 2026

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Updated (UTC)
✅ Deployment successful!
View logs
supermemory-mcp f14cdd7 Aug 02 2026, 05:38 AM

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jul 21, 2026

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
supermemory-app f14cdd7 Commit Preview URL

Branch Preview URL
Aug 02 2026, 05:39 AM

Copy link
Copy Markdown
Member Author

How to use the Graphite Merge Queue

Add the label Main to this PR to add it to the merge queue.

You must have a Graphite account in order to use the merge queue. Sign up using this link.

An organization admin has enabled the Graphite Merge Queue in this repository.

Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue.

This stack of pull requests is managed by Graphite. Learn more about stacking.

@sreedharsreeram
sreedharsreeram marked this pull request as ready for review July 21, 2026 06:16
@claude

claude Bot commented Jul 21, 2026

Copy link
Copy Markdown

Claude finished @sreedharsreeram's task in 1m 45s —— View job


PR Review Complete

  • Get PR diff and analyze changes
  • Review for bugs, security issues, and logic errors
  • Check existing review comments to avoid duplicates
  • Submit review summary

Overview: Adds a Skills settings UI with org-wide and personal sections, Markdown upload, scoped editing, and approval workflows for Company Brain.

Issues found: None — this looks good to ship.

All previously reported P2 issues have been addressed:

  1. Section switching data loss — Fixed. skillsDirty state is lifted to ConfigureView via onUnsavedChangesChange with a confirmation dialog guarding section changes.

  2. Invalidation race condition — Fixed. Hook-level onSuccess uses void invalidate() (fire-and-forget), ensuring per-call callbacks (toast + close) execute before any refetch-triggered remount.

  3. Dirty tracking normalization — Fixed. skillDraftsEqual compares normalized drafts, so trailing whitespace alone won't enable Save.

  4. Indented --- frontmatter parsing — Not a bug. The regex /^---[\t ]*$/ correctly requires the delimiter at column 0.

The implementation is solid:

  • Server-driven permissions (canEdit/canDelete/canDecide) with proper client guards
  • Optimistic locking via expectedVersion with 409 conflict recovery
  • XSS-safe Markdown rendering (ReactMarkdown without rehypeRaw)
  • Byte-based body validation using TextEncoder for accurate 16KB limit enforcement
  • Custom BrainSkillRequestError class with proper response parsing and fallback messages

Score: 10/10

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

Overview: Adds a Skills settings UI with org-wide and personal sections, including Markdown upload, scoped editing, and approval workflows.

Issues found: None — this looks good to ship.

The implementation is solid:

  • Permissions: Server-driven canEdit/canDelete/canDecide flags with proper client-side guards
  • Concurrency: Uses expectedVersion optimistic locking for approve/reject operations with 409 conflict handling
  • XSS safety: ReactMarkdown renders markdown to React elements (no rehypeRaw), blocking raw HTML injection
  • Input validation: skillDraftPayload enforces name/description/body requirements with 16KB body limit
  • Memory safety: LCS diff algorithm bounds allocation at 200K operations and falls back to simpler prefix/suffix diffing for line-dense bodies
  • Error handling: Custom BrainSkillRequestError class with proper response parsing and fallback messages

Score: 10/10

@polylane

polylane Bot commented Jul 21, 2026

Copy link
Copy Markdown

Note

Production impact unlikely.

Checked all 8 changed files against supermemory-app config and routing; purely additive — new Skills tab, 6 new files using only existing deps, generic [section] route already handles the id, no existing bindings/routes/API contracts modified.

View the full analysis →

view-investigation review-in-polylane disable-pr-reviews

Polylane analysed 4ee6a25 for production impact.

@vorflux vorflux Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Found three reproducible data-loss and feedback issues in the skills settings UI. Details are inline.


Review with Vorflux

Comment thread apps/web/components/settings/company-brain-skills.tsx Outdated
Comment thread apps/web/components/settings/company-brain-skills/skill-editor.tsx Outdated
Comment thread apps/web/components/settings/company-brain-skills/skill-editor.tsx Outdated
@sreedharsreeram
sreedharsreeram force-pushed the sreedharsreeram/taipei-v1 branch 2 times, most recently from adc01d9 to 3a28d57 Compare July 21, 2026 19:09

@vorflux vorflux Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Re-audited the full updated diff at 3a28d571. The three previously reported frontend issues are resolved; three additional reproducible issues remain and are detailed inline.


Review with Vorflux

Comment thread apps/web/components/configure-view.tsx Outdated
Comment thread apps/web/hooks/use-brain-skills.impl.ts Outdated
Comment thread apps/web/components/settings/company-brain-skills/domain.ts Outdated
@sreedharsreeram
sreedharsreeram force-pushed the sreedharsreeram/taipei-v1 branch from 3a28d57 to 4e5788a Compare July 21, 2026 21:35

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

Overview: Adds a Skills settings UI with org-wide and personal sections, Markdown upload, scoped editing, and approval workflows for Company Brain.

Issues found: Vorflux identified 3 P2 issues in the latest review cycle. After independent analysis:

  1. configure-view.tsx:139 — Section switching data loss ✓ Confirmed. The CompanyBrainSkills component holds all draft/dirty state locally, so switching to Integrations/Models/Automations unmounts it and silently discards unsaved work. The existing discard dialog only guards card-to-card switches within Skills, not section changes.

  2. use-brain-skills.impl.ts:135 — Invalidation race condition ✓ Confirmed. onSuccess: invalidate returns a Promise from invalidateQueries(). When the refetch updates skill.version, the editor's key changes, unmounting it before the per-call onSuccess (toast + onClose()) can run. Move the toast/close into the hook-level callback or call them before awaiting invalidation.

  3. domain.ts — Indented --- closes frontmatter — I believe this is a false positive. The regex /^---[\t ]*$/ at line 189 requires --- at column 0; an indented --- like --- inside a block scalar won't match. The block scalar trimming at line 215 only affects the collected value, not the findIndex that determines end.

No additional bugs, security vulnerabilities, or logic errors found beyond what was already flagged.

Score: 8/10 — Two confirmed data-loss/UX issues need fixing before merge; the implementation is otherwise solid with proper permission checks, optimistic locking, and XSS-safe Markdown rendering.

Comment on lines +91 to +100
const addDraft = (kind: UnsavedDraft["kind"], draft: SkillDraft) => {
setDrafts((current) => [
...current,
{
key: draftKey.current++,
kind,
draft: skillDraftForRole(draft, isAdmin),
},
])
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The rule 'Use function declarations over function expressions' is violated here. addDraft is defined as a const arrow function expression inside the component body. It should either be a named function declaration (if hoisting is needed) or, since it's a callback/helper inside a component, at minimum it should be noted that the style guide prefers function declarations. However, since this is inside a React component body (not a module-level function), the more applicable sub-rule is that arrow functions should be used for concise callbacks, but standalone helpers like addDraft, removeDraft, closeOpenSkill, requestOpenSkill, and confirmOpenSkill are defined as const arrow function expressions rather than function declarations. Per the style guide: 'Use function declarations over function expressions.' These should be declared as function addDraft(...), function removeDraft(...), etc.

Spotted by Graphite (based on custom rule: TypeScript style guide (Google))

Fix in Graphite


Is this helpful? React 👍 or 👎 to let us know.

Comment on lines +159 to +178
const renderSkill = (skill: BrainSkill) =>
openId === skill.id ? (
<div key={skill.id} className="sm:col-span-2 lg:col-span-3">
<SkillEditor
key={`${skill.id}:${skill.version}:${skill.updatedAt}`}
skill={skill}
initialDraft={draftFromSkill(skill)}
isAdmin={isAdmin}
viewerId={viewerId}
onClose={closeOpenSkill}
onDirtyChange={setOpenSkillDirty}
/>
</div>
) : (
<SkillCard
key={skill.id}
skill={skill}
onOpen={() => requestOpenSkill(skill.id)}
/>
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The rule 'Use function declarations over function expressions' is violated here. renderSkill and renderDraft are defined as const arrow function expressions (lines 159 and 179). These are standalone helper functions, not inline callbacks, and should be declared as function declarations: function renderSkill(skill: BrainSkill) { ... } and function renderDraft({ key, kind, draft }: UnsavedDraft) { ... } instead of const renderSkill = (...) => and const renderDraft = (...) =>.

Spotted by Graphite (based on custom rule: TypeScript style guide (Google))

Fix in Graphite


Is this helpful? React 👍 or 👎 to let us know.

Comment on lines +268 to +278
const resetErrors = () => {
setClientError(null)
save.reset()
remove.reset()
approve.reset()
reject.reset()
}
const set = <K extends keyof SkillDraft>(key: K, value: SkillDraft[K]) => {
resetErrors()
setDraft((current) => ({ ...current, [key]: value }))
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The rule 'Use function declarations over function expressions' is violated here. resetErrors and set are defined as const arrow function expressions inside the component body (lines 268 and 275). These are standalone helper functions, not inline callbacks, and should be declared as function declarations: function resetErrors() { ... } and function set<K extends keyof SkillDraft>(key: K, value: SkillDraft[K]) { ... }.

Spotted by Graphite (based on custom rule: TypeScript style guide (Google))

Fix in Graphite


Is this helpful? React 👍 or 👎 to let us know.

value={draft.body}
onChange={(event) => set("body", event.target.value)}
disabled={busy}
maxLength={SKILL_BODY_MAX_LENGTH}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The maxLength attribute counts UTF-16 code units (characters), but validation in domain.ts line 95 checks UTF-8 bytes using new TextEncoder().encode(body).length. Users can type multi-byte characters (emoji, non-Latin scripts) and hit the 16,384 character limit while staying under 16KB in bytes, or conversely, fill the textarea with multi-byte characters that exceed 16KB in bytes before hitting the character limit, causing a confusing validation error on save.

// Remove maxLength from textarea since byte-based validation
// will handle the limit more accurately
<textarea
  value={draft.body}
  onChange={(event) => set("body", event.target.value)}
  disabled={busy}
  // maxLength={SKILL_BODY_MAX_LENGTH} <- Remove this
  spellCheck={false}

Spotted by Graphite

Fix in Graphite


Is this helpful? React 👍 or 👎 to let us know.

@sreedharsreeram
sreedharsreeram force-pushed the sreedharsreeram/taipei-v1 branch 2 times, most recently from 3aa8371 to 2761dc9 Compare July 21, 2026 22:55

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

Overview: Adds a Skills settings UI with org-wide and personal sections, Markdown upload, scoped editing, and approval workflows for Company Brain.

Issues found: None — this looks good to ship.

All previously reported P2 issues have been resolved:

  1. Section switching data loss — Fixed. skillsDirty state is now lifted to ConfigureView and passed via onUnsavedChangesChange. A confirmation dialog guards section changes when Skills has unsaved edits.

  2. Invalidation race condition — Fixed. Hook-level onSuccess now uses void invalidate() (fire-and-forget), ensuring per-call callbacks (toast + close) execute before any refetch-triggered remount.

  3. Indented --- frontmatter parsing — Not a bug. The regex /^---[\t ]*$/ correctly requires the delimiter at column 0; indented lines inside block scalars won't match.

The implementation is solid:

  • Server-driven permissions (canEdit/canDelete) with proper client guards
  • Optimistic locking via expectedVersion with 409 conflict recovery
  • XSS-safe Markdown rendering (ReactMarkdown without rehypeRaw)
  • Proper error handling with BrainSkillRequestError class and fallback messages

Score: 10/10

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

Overview: Adds a Skills settings UI with org-wide and personal sections, Markdown upload, scoped editing, and approval workflows for Company Brain.

Issues found: None — this looks good to ship.

All previously reported P2 issues have been addressed:

  1. Section switching data loss — Fixed. skillsDirty state is lifted to ConfigureView and passed via onUnsavedChangesChange. A confirmation dialog guards section changes when Skills has unsaved edits.

  2. Invalidation race condition — Fixed. Hook-level onSuccess now uses void invalidate() (fire-and-forget), ensuring per-call callbacks (toast + close) execute before any refetch-triggered remount.

  3. Dirty tracking normalization — Fixed. skillDraftsEqual compares normalized drafts, so trailing whitespace alone won't enable Save or trigger unnecessary version bumps.

The implementation is solid:

  • Server-driven permissions (canEdit/canDelete) with proper client guards
  • Optimistic locking via expectedVersion with 409 conflict recovery
  • XSS-safe Markdown rendering (ReactMarkdown without rehypeRaw)
  • Proper YAML frontmatter parsing with /^---[\t ]*$/ requiring delimiter at column 0
  • Byte-based body validation using TextEncoder for accurate 16KB limit enforcement

Score: 10/10

@graphite-app

graphite-app Bot commented Aug 2, 2026

Copy link
Copy Markdown

Merge activity

## Stack Context

This is the frontend half of the Company Brain Skills feature. The harness is implemented in supermemoryai/mono#2611.

## What?

Add Skills settings with separate Org-wide and Personal sections, Markdown upload autofill, scoped creation and editing, approval controls, and server-driven permissions.

## Why?

Members need a focused way to manage their private playbooks while admins create and approve organization-wide guidance.

## Related

- Harness: supermemoryai/mono#2611

---
**Session Details**
- Session: [View Session](https://supermemory.us1.vorflux.com/agent-sessions/d8c77451-8f55-47ab-a182-5c98da616263)
- Requested by: Sreeram Sreedhar (sreeram@supermemory.com)
- Address comments on this PR. Add `(aside)` to your comment to have me ignore it.
@graphite-app
graphite-app Bot force-pushed the sreedharsreeram/taipei-v1 branch from 4ee6a25 to f14cdd7 Compare August 2, 2026 05:36
@graphite-app
graphite-app Bot merged commit f14cdd7 into main Aug 2, 2026
6 of 8 checks passed
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.

2 participants