Skip to content

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

Open
sreedharsreeram wants to merge 1 commit into
mainfrom
sreedharsreeram/taipei-v1
Open

feat(web): add Company Brain skills settings#1322
sreedharsreeram wants to merge 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 2761dc9 Jul 21 2026, 10:56 PM

@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 2761dc9 Commit Preview URL

Branch Preview URL
Jul 21 2026, 10:57 PM

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 2m 24s —— View job


Review Complete

  • Load review tools
  • Fetch PR diff and existing review comments
  • Analyze changes for bugs, security issues, and logic errors
  • Check if previously reported issues have been addressed
  • Submit review

Result: All previously reported P2 issues have been resolved. No new bugs, security issues, or logic errors found.

Issue Status
Section switching data loss Fixed — dirty state lifted to parent with confirmation dialog
Invalidation race condition Fixed — void invalidate() prevents callback blocking
Indented --- frontmatter Not a bug — regex requires column 0

Score: 10/10 — Ready to ship.

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

Re-reviewed at 3a28d57: purely additive frontend — new Skills tab and 6 new files. No bindings, routes, or API contracts on supermemory-app are modified or removed.


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

Polylane analysed 3a28d57 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
@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 from 4e5788a to 3aa8371 Compare July 21, 2026 21:40
## Stack Context

This is the frontend half of the Company Brain Skills feature. A separate harness PR provides the API and runtime behavior.

## What?

Add Skills settings with separate Org-wide and Personal sections, Markdown upload autofill, server-driven permissions, and org-wide authoring controls available only to admins and owners. Authorized org-wide changes save immediately without a review queue.

## Why?

Members need a focused way to manage private playbooks while admins and owners manage organization-wide guidance that everyone can see and use.
@sreedharsreeram
sreedharsreeram force-pushed the sreedharsreeram/taipei-v1 branch 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

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