Skip to content

feat(skills): disable skills from PromptComposer and terminal AI Input - #167

Merged
AruNi-01 merged 5 commits into
mainfrom
aarynlu/composer-skills-disable-e812
Jul 22, 2026
Merged

AruNi-01 merged 5 commits into
mainfrom
aarynlu/composer-skills-disable-e812

Conversation

@AruNi-01

@AruNi-01 AruNi-01 commented Jul 22, 2026 •

Copy link
Copy Markdown
Owner

Summary

Adds dynamic skill enable/disable controls to PromptComposer (Welcome) and terminal AI Input, aligned with the Skills management page.

Behavior

  • Project: uses existing skills_set_enabled move into project/.atmos/skills/.disabled/... so composer toggles stay in sync with the Skills page.
  • Workspace: scans/manages skills under the workplace path; disabled entries go to workplace/.atmos/skills/.disabled/....
  • Sync dirs (symlink / copy): same move API. If a parent agent dir is a compensated symlink into the project, ancestors are materialized into per-child symlinks first so the move does not mutate the project tree.
  • UI tip: disable takes effect on a new Agent session; already-initialized sessions keep skills already loaded into the system prompt.

Key changes

  • Spec: APP-040_composer-skills-disable
  • Backend: workspace manageable scope, skills_scan_root, optional scope_root on skills_set_enabled, symlink materialization helper + unit tests (S1–S3 green)
  • Frontend: shared ComposerSkillsControl wired into Welcome composer + terminal overlays / side chat

Test plan

  • cargo +stable test -p core-service --lib service::skill::tests (project disable, workspace copy, parent-symlink)
  • cargo +stable check -p api
  • Manual: open Welcome PromptComposer → Skills → toggle project skill → confirm Skills page status matches after refresh
  • Manual: in a workspace terminal AI Input → toggle a synced skill → confirm workplace .disabled and project tree unchanged for symlink case
  • Confirm session tip copy is visible in the popover (en/zh)
Open in Web Open in Cursor 

Summary by cubic

Add Dynamic Skills toggles to PromptComposer and terminal AI Input so you can enable/disable skills per project or workspace without leaving where you’re typing. Changes take effect immediately via a live-path SKILL_DISABLED.md marker, and moves persist under .atmos/skills/.disabled for easy restore.

  • New Features

    • Shared ComposerSkillsControl and a slash-menu “Dynamic Skills” view in Welcome composer, terminal overlays, and side chat.
    • Workspace scope: composer scans one root via skills_scan_root and passes optional scope_root to skills_set_enabled; disabled trees live under <scope>/.atmos/skills/.disabled/... (project uses <project>/.atmos/skills/.disabled/...).
    • Immediate effect and persistence: writes SKILL_DISABLED.md at the live path, scanner skips these markers, and symlink ancestor materialization keeps workspace moves from mutating the project; added en/zh copy and a new “How It Works: Dynamic Skills” doc.
  • Bug Fixes

    • Side chat now passes the real project GUID as projectId for project-mode toggles.
    • Canvas workspace side-chat skills context stays valid, and prompt whitespace is preserved when removing the disable chip.
    • Aligned docs/spec copy.

Written for commit 896d552. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • New Features
    • Added “Dynamic Skills” controls to temporarily enable/disable skills from the Welcome composer and terminal AI input via the / menu.
    • Extended skill scope support with “workspace” for scanning and managing skills at the current workspace level.
    • Added an in-command disable-skills view, session-aware disable chips, and updated scope labels/filters throughout the UI.
  • Tests
    • Added automated coverage for project vs workspace disable/enable behavior, including symlink-safe workspace handling.
  • Documentation
    • Added Dynamic Skills documentation (including how project/workspace behavior differs) and updated the skill management guide.

Add a shared composer skills control that toggles manageable skills using
the same .atmos/skills/.disabled move as the Skills page for projects, and
workplace-rooted disable for workspaces (with symlink ancestor materialization
so sync-dir copies/symlinks stay local). Tip users that changes apply on new
Agent sessions only.

Co-authored-by: AruNi_Lu <hello@0x3f4.run>
@vercel

vercel Bot commented Jul 22, 2026 •

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
atmos-landing Ready Ready Preview, Comment Jul 22, 2026 11:54am

@coderabbitai

coderabbitai Bot commented Jul 22, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Adds project/workspace-aware skill scanning and enable/disable operations, safe symlink handling, WebSocket contracts, and Dynamic Skills controls for Welcome and terminal composer interfaces.

Changes

Composer Skills Disable

Layer / File(s) Summary
Root-aware skill storage and validation
crates/core-service/src/service/skill*
Skill scanning and toggling now accept project/workspace roots, localize symlinked paths, ignore disabled markers during scans, and test project, workspace-copy, and symlink behavior.
WebSocket root-scan contract
apps/api/src/api/ws/*, apps/web/src/api/ws/skills-api.ts, apps/web/src/features/connection/hooks/use-websocket.ts
Adds root DTOs, the skills_scan_root action, root scanning, and optional scope-root toggle data.
Composer skill control and protocol
apps/web/src/features/skills/*, apps/web/messages/{en,zh}.json, apps/web/src/features/welcome/components/SlashCommandPopover.tsx
Adds workspace-aware loading and toggling, scope metadata, localized controls, and session tracking for Dynamic Skills.
Welcome composer integration
apps/web/src/features/welcome/components/*, apps/web/src/features/welcome/hooks/*, apps/web/src/features/welcome/lib/*
Adds the Dynamic Skills slash view, disabled-skill filtering, context-aware loading, and PromptComposer session wiring.
Terminal integration
apps/web/src/features/terminal/*, apps/web/src/features/canvas/components/CanvasTerminalCard.tsx
Passes project/workspace contexts into terminal overlays and exposes the Dynamic Skills disable view.
Feature specifications and documentation
specs/APP/APP-040_composer-skills-disable/*, specs/README.md, apps/docs/content/docs/(app)/*
Documents requirements, architecture, test scenarios, Dynamic Skills behavior, and the new documentation navigation entry.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Composer
  participant skillsApi
  participant WsMessageService
  participant SkillManager
  Composer->>skillsApi: scanRoot or setEnabled
  skillsApi->>WsMessageService: send WebSocket request
  WsMessageService->>SkillManager: scan or toggle skill
  SkillManager-->>WsMessageService: return skills or success
  WsMessageService-->>skillsApi: return JSON response
  skillsApi-->>Composer: update skill state and session chip
Loading

Possibly related PRs

  • AruNi-01/atmos#15: Introduced the placement-aware skill enable/disable flow extended here with workspace root context.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 31.43% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: disabling skills from PromptComposer and terminal AI Input.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch aarynlu/composer-skills-disable-e812

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Jul 22, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds Dynamic Skills controls to the composer and terminal input. The main changes are:

  • New project and workspace skill toggles in composer surfaces.
  • WebSocket messages for scanning a single skill root and toggling with an optional scope root.
  • Backend skill handling for workspace roots and symlink-safe disable moves.
  • Updated docs, translations, and tests for the Dynamic Skills flow.

Confidence Score: 5/5

This looks safe to merge.

  • No blocking issues found in the changed code.

Important Files Changed

Filename Overview
apps/web/src/features/terminal/components/TerminalSideChatModal.tsx Builds project or workspace Dynamic Skills context for terminal side chats.
apps/web/src/features/terminal/hooks/use-terminal-side-chats.tsx Threads the project id into the terminal side-chat layer.
apps/web/src/features/canvas/components/CanvasTerminalCard.tsx Passes the canvas terminal scope id into side-chat skill controls and keeps workplace terminals in workspace mode.
apps/web/src/features/skills/components/ComposerSkillsControl.tsx Adds the shared Dynamic Skills popover and project/workspace skill loading behavior.
apps/api/src/api/ws/router/skills.rs Adds WebSocket handlers for scoped root scans and scoped skill toggles.

Reviews (5): Last reviewed commit: "fix(skills): address Dynamic Skills revi..." | Re-trigger Greptile

Comment thread apps/web/src/features/terminal/components/TerminalSideChatModal.tsx Outdated
@github-actions

github-actions Bot commented Jul 22, 2026 •

Copy link
Copy Markdown

E2E report (expired)

This report has been superseded by a newer CI - E2E run.

Field Value
Superseded by run 29885663897
Previous HTML report Open report

@AruNi-01
AruNi-01 marked this pull request as ready for review July 22, 2026 02:16
…ain, and use that for project-mode skills context instead of workspaceId.
Comment thread apps/web/src/features/canvas/components/CanvasTerminalCard.tsx

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

Actionable comments posted: 11

🧹 Nitpick comments (3)
apps/web/src/features/terminal/components/terminal-mosaic-scoped-pane-window.tsx (1)

156-173: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicate skill-context derivation logic across terminal pane components.

This block is duplicated verbatim in terminal-mosaic-workspace-pane-window.tsx (L185-202), and a divergent (buggy) variant exists in TerminalSideChatModal.tsx (L81-100). See consolidated comment for the cross-file recommendation.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@apps/web/src/features/terminal/components/terminal-mosaic-scoped-pane-window.tsx`
around lines 156 - 173, Extract the shared skills-context derivation into a
reusable helper or hook, then replace the duplicated logic in
terminal-mosaic-scoped-pane-window.tsx and
terminal-mosaic-workspace-pane-window.tsx with it. Update
TerminalSideChatModal.tsx to use the same implementation so project and
workspace contexts consistently handle local paths, active projects, IDs, names,
and paths.
apps/web/src/features/skills/components/ComposerSkillsControl.tsx (1)

58-261: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

Consider adding basic tests for this new interactive component.

ComposerSkillsControl has non-trivial async state (dual-fetch merge for workspace mode, optimistic toggle with rollback-on-error) but ships with no accompanying test file in this batch. A few unit tests (loadSkills merge logic, handleToggle success/error paths) would guard this critical toggle path against regressions.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/src/features/skills/components/ComposerSkillsControl.tsx` around
lines 58 - 261, The new ComposerSkillsControl interactive flow lacks regression
coverage. Add focused unit tests for loadSkills, including workspace dual-fetch
merging and filtering, and for handleToggle success and error paths, verifying
optimistic state updates, refresh/invalidation calls, rollback reload behavior,
and user-facing errors without changing production behavior.
apps/web/src/features/terminal/components/TerminalSideChatModal.tsx (1)

1-1: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Three components hand-roll the same ComposerSkillsContext derivation; extract a shared hook. The duplicated logic already diverged once (see the TerminalSideChatModal.tsx major-issue comment), which is exactly the kind of drift a shared helper would prevent.

  • apps/web/src/features/terminal/components/TerminalSideChatModal.tsx#L81-100: replace this local derivation with the shared hook/helper, sourcing a real project id instead of workspaceId for the project-mode branch.
  • apps/web/src/features/terminal/components/terminal-mosaic-scoped-pane-window.tsx#L156-173: replace this block with a call to the shared hook (using its already-resolved activeProject).
  • apps/web/src/features/terminal/components/terminal-mosaic-workspace-pane-window.tsx#L185-202: replace this identical block with the same shared hook call.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/src/features/terminal/components/TerminalSideChatModal.tsx` at line
1, Extract the duplicated ComposerSkillsContext derivation into a shared
hook/helper and use it from TerminalSideChatModal,
terminal-mosaic-scoped-pane-window, and terminal-mosaic-workspace-pane-window.
In TerminalSideChatModal, pass the actual project id for project mode instead of
workspaceId; in the two mosaic components, pass their existing resolved
activeProject. Remove each local derivation while preserving the current context
behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/api/src/api/ws/router/skills.rs`:
- Around line 144-146: Wrap the synchronous
SkillManager::set_enabled_with_extra_roots call in spawn_blocking within the
async handler, moving or cloning the required project_paths and extra_roots into
the blocking closure. Await the JoinHandle and propagate both join failures and
the service error before continuing the handler flow.
- Around line 133-142: Both handlers must stop trusting client-supplied
skill-root path, id, and name values: in apps/api/src/api/ws/router/skills.rs
lines 133-142, replace the direct SkillScopeRoot mapping before
set_enabled_with_extra_roots with an authenticated project/workspace lookup,
canonicalize its path, and reject mismatches; apply the same server-owned root
resolution and validation at lines 162-167 before scan_root.

In `@apps/web/src/features/skills/components/ComposerSkillsControl.tsx`:
- Around line 42-56: Update scopeLabel to handle the inside_project and system
SkillInfo.scope values with their corresponding translation keys, following the
existing t("scope.*") pattern; remove the raw skill.scope fallback so every
supported scope returns a translated label.

In `@apps/web/src/features/skills/components/InstalledSkillListCard.tsx`:
- Around line 43-48: Update getScopeMeta to accept the translator and replace
the hardcoded workspace label with the localized scope.workspace key, matching
SkillDetail.tsx. Ensure the InstalledSkillListCard path obtains the translator
via useTranslations and passes it into getScopeMeta while preserving the
existing metadata.

In `@apps/web/src/features/terminal/components/TerminalSideChatModal.tsx`:
- Around line 81-100: Update the project-root branch of the skillsContext
useMemo in TerminalSideChatModal to use the resolved active project id, matching
the sibling terminal pane behavior, instead of workspaceId. Preserve workspaceId
for non-project workspace contexts and ensure the real project id reaches
ComposerSkillsControl for project skill filtering.

In `@crates/core-service/src/service/skill/support.rs`:
- Around line 147-210: Normalize the path used by ensure_entry_local_to_root
before calling find_symlink_ancestor so it is in the same canonical form as
root, while preserving the existing validation behavior for missing or invalid
paths. Update find_symlink_ancestor’s candidate-prefix comparisons to use this
normalized path, ensuring ancestor traversal still reaches parent symlinks when
root resolves differently from the raw path.

In `@specs/APP/APP-040_composer-skills-disable/PRD.md`:
- Line 26: Update the M5 requirement to replace “Parent compensated symlinks”
with “parent symlinks in compensated trees,” or define “compensated symlink”
before using it, while preserving the existing behavior describing
materialization without mutating the project tree.

In `@specs/APP/APP-040_composer-skills-disable/TECH.md`:
- Around line 51-53: Update the scope-selection logic in the
TerminalAgentInputShell footer to resolve the nearest canonical workspace
worktree ancestor of localPath, rather than checking only exact root equality.
Use workspace mode when an ancestor is found, and retain
activeProjectId/project-root project mode only when no workspace ancestor
exists.
- Around line 43-44: Update the server-side handling of skills_set_enabled and
skills_scan_root so scope_root.path is resolved from authenticated server state
or rejected unless it exactly matches a known workspace root; do not trust
arbitrary client-provided absolute paths when performing scans or moves.

In `@specs/APP/APP-040_composer-skills-disable/TEST.md`:
- Around line 3-8: Expand the TEST.md test plan beyond the current “manual /
agent-browser” note to include test strategy, coverage and execution maps,
concrete scenarios with setup/actions/assertions, exploratory checks, regression
checklist, acceptance criteria, manual verification steps, and explicit
non-coverage. Document the required Agent Browser skill/setup procedure and
record a not_run outcome when setup is unavailable, then add a post-run Coverage
Status section summarizing execution results.
- Around line 20-28: Reconcile the S1–S3 entries in the execution map with the
command evidence and “Coverage Status,” using a single consistent status source.
Update the acceptance checklist for the tests that actually passed, while
keeping the manual S4–S5 items pending and unchecked until executed.

---

Nitpick comments:
In `@apps/web/src/features/skills/components/ComposerSkillsControl.tsx`:
- Around line 58-261: The new ComposerSkillsControl interactive flow lacks
regression coverage. Add focused unit tests for loadSkills, including workspace
dual-fetch merging and filtering, and for handleToggle success and error paths,
verifying optimistic state updates, refresh/invalidation calls, rollback reload
behavior, and user-facing errors without changing production behavior.

In
`@apps/web/src/features/terminal/components/terminal-mosaic-scoped-pane-window.tsx`:
- Around line 156-173: Extract the shared skills-context derivation into a
reusable helper or hook, then replace the duplicated logic in
terminal-mosaic-scoped-pane-window.tsx and
terminal-mosaic-workspace-pane-window.tsx with it. Update
TerminalSideChatModal.tsx to use the same implementation so project and
workspace contexts consistently handle local paths, active projects, IDs, names,
and paths.

In `@apps/web/src/features/terminal/components/TerminalSideChatModal.tsx`:
- Line 1: Extract the duplicated ComposerSkillsContext derivation into a shared
hook/helper and use it from TerminalSideChatModal,
terminal-mosaic-scoped-pane-window, and terminal-mosaic-workspace-pane-window.
In TerminalSideChatModal, pass the actual project id for project mode instead of
workspaceId; in the two mosaic components, pass their existing resolved
activeProject. Remove each local derivation while preserving the current context
behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6128c241-08b7-482b-86b7-2fc036145dda

📥 Commits

Reviewing files that changed from the base of the PR and between ced7dbf and b87be13.

📒 Files selected for processing (28)
  • apps/api/src/api/ws/message.rs
  • apps/api/src/api/ws/message/skills.rs
  • apps/api/src/api/ws/router/mod.rs
  • apps/api/src/api/ws/router/skills.rs
  • apps/web/messages/en.json
  • apps/web/messages/zh.json
  • apps/web/src/api/ws/skills-api.ts
  • apps/web/src/features/connection/hooks/use-websocket.ts
  • apps/web/src/features/skills/components/ComposerSkillsControl.tsx
  • apps/web/src/features/skills/components/InstalledSkillListCard.tsx
  • apps/web/src/features/skills/components/SkillDetail.tsx
  • apps/web/src/features/terminal/components/TerminalAgentInputOverlay.tsx
  • apps/web/src/features/terminal/components/TerminalSideChatModal.tsx
  • apps/web/src/features/terminal/components/terminal-mosaic-scoped-pane-window.tsx
  • apps/web/src/features/terminal/components/terminal-mosaic-workspace-pane-window.tsx
  • apps/web/src/features/welcome/components/SlashCommandPopover.tsx
  • apps/web/src/features/welcome/components/WelcomeComposerCard.tsx
  • apps/web/src/features/welcome/components/WelcomeComposerControls.tsx
  • apps/web/src/features/welcome/components/WelcomePage.tsx
  • crates/core-service/src/service/skill.rs
  • crates/core-service/src/service/skill/scanner.rs
  • crates/core-service/src/service/skill/support.rs
  • crates/core-service/src/service/skill/tests.rs
  • specs/APP/APP-040_composer-skills-disable/BRAINSTORM.md
  • specs/APP/APP-040_composer-skills-disable/PRD.md
  • specs/APP/APP-040_composer-skills-disable/TECH.md
  • specs/APP/APP-040_composer-skills-disable/TEST.md
  • specs/README.md

Comment on lines +133 to +142
let extra_roots: Vec<SkillScopeRoot> = req
.scope_root
.into_iter()
.map(|root| SkillScopeRoot {
scope: root.scope,
id: root.id,
name: root.name,
path: root.path,
})
.collect();

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.

🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Map the target file and nearby symbols
ast-grep outline apps/api/src/api/ws/router/skills.rs --view expanded || true

# Show the relevant section with line numbers
sed -n '1,260p' apps/api/src/api/ws/router/skills.rs | cat -n

# Find the request/validation types and any helpers used by these routes
rg -n "SkillScopeRoot|scope_root|SkillsScanRootRequest|set_enabled_with_extra_roots|scan" apps/api/src/api/ws/router/skills.rs apps/api/src/api/ws -S

Repository: AruNi-01/atmos

Length of output: 18560


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect related service and repository types referenced by the router
rg -n "set_enabled_with_extra_roots|SkillScopeRoot|SkillsScanRootRequest|canonical|path" crates apps/api -S

# Locate definitions for server-owned project/workspace records and any root resolution helpers
rg -n "project.*record|workspace.*record|resolve.*root|root.*resolver|authorized.*root|registered.*root" crates apps/api -S

Repository: AruNi-01/atmos

Length of output: 50371


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Show the service signatures and implementations for the skills operations
rg -n "set_enabled_with_extra_roots|scan_root|SkillScopeRoot|SkillsScanRootRequest" crates -S

# If found, print the surrounding implementation
files=$(rg -l "set_enabled_with_extra_roots|SkillsScanRootRequest" crates -S || true)
for f in $files; do
  echo "===== $f ====="
  sed -n '1,260p' "$f" | cat -n
done

Repository: AruNi-01/atmos

Length of output: 21325


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the request DTOs and any root-related schema/types
rg -n "struct SkillsScanRootRequest|struct SkillScopeRoot|enum .*Skill.*Request|scope_root" apps crates -S

Repository: AruNi-01/atmos

Length of output: 2199


🏁 Script executed:

#!/bin/bash
set -euo pipefail

sed -n '1,140p' apps/api/src/api/ws/message/skills.rs | cat -n
echo '===== web api ====='
sed -n '1,180p' apps/web/src/api/ws/skills-api.ts | cat -n

Repository: AruNi-01/atmos

Length of output: 8085


🏁 Script executed:

#!/bin/bash
set -euo pipefail

sed -n '1,220p' crates/core-service/src/service/skill/scanner.rs | cat -n
echo '===== support ====='
sed -n '1,220p' crates/core-service/src/service/skill/support.rs | cat -n

Repository: AruNi-01/atmos

Length of output: 17656


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Focus on the root-based scanning logic and any path validation/canonicalization.
rg -n "fn scan_root|derive_original_path|canonical|strip_prefix|root_path|project_id|scope_root" crates/core-service/src/service/skill/scanner.rs crates/core-service/src/service/skill/support.rs -n -S
sed -n '220,420p' crates/core-service/src/service/skill/scanner.rs | cat -n
sed -n '420,620p' crates/core-service/src/service/skill/scanner.rs | cat -n

Repository: AruNi-01/atmos

Length of output: 21112


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Find direct tests or call sites for scan_root and extra_roots behavior
rg -n "scan_root\(|scan_all_with_extra_roots|set_enabled_with_extra_roots|SkillsScanRootRequest|scope_root" crates/core-service/src/service/skill tests apps/api/src/api/ws -S

Repository: AruNi-01/atmos

Length of output: 3023


🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n "scanRoot\\(" apps/web apps/api -S
echo '===== call sites ====='
rg -n "skills_scan_root|skills_set_enabled|scopeRoot|scope_root" apps/web/src -S

Repository: AruNi-01/atmos

Length of output: 1164


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Check whether the UI sources roots from server-owned project/workspace data.
sed -n '1,220p' apps/web/src/api/ws/skills-api.ts | cat -n
echo '===== likely consumers ====='
rg -n "skillsApi\\.scanRoot|skillsApi\\.setEnabled|scopeRoot" apps/web/src -S

Repository: AruNi-01/atmos

Length of output: 7154


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the relevant tests to see how root handling is expected to behave.
sed -n '260,360p' crates/core-service/src/service/skill/tests.rs | cat -n

Repository: AruNi-01/atmos

Length of output: 4242


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the path validation helper that controls move safety, if any.
sed -n '220,340p' crates/core-service/src/service/skill/support.rs | cat -n

Repository: AruNi-01/atmos

Length of output: 4707


🏁 Script executed:

#!/bin/bash
set -euo pipefail

sed -n '60,210p' apps/web/src/features/skills/components/ComposerSkillsControl.tsx | cat -n

Repository: AruNi-01/atmos

Length of output: 6133


Bind skill roots to server-owned project/workspace records. Both handlers accept client-supplied path/id/name, and core_service only checks scope plus existence, so a forged project/workspace root can leak skill metadata and steer enable/disable moves onto an arbitrary directory.

  • apps/api/src/api/ws/router/skills.rs#L133-L142: resolve scope_root from authenticated project/workspace data, canonicalize the path, and reject mismatches before calling set_enabled_with_extra_roots.
  • apps/api/src/api/ws/router/skills.rs#L162-L167: apply the same server-side root lookup before scan_root.
📍 Affects 1 file
  • apps/api/src/api/ws/router/skills.rs#L133-L142 (this comment)
  • apps/api/src/api/ws/router/skills.rs#L162-L167
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/api/src/api/ws/router/skills.rs` around lines 133 - 142, Both handlers
must stop trusting client-supplied skill-root path, id, and name values: in
apps/api/src/api/ws/router/skills.rs lines 133-142, replace the direct
SkillScopeRoot mapping before set_enabled_with_extra_roots with an authenticated
project/workspace lookup, canonicalize its path, and reject mismatches; apply
the same server-owned root resolution and validation at lines 162-167 before
scan_root.

Comment on lines +144 to +146
SkillManager::set_enabled_with_extra_roots(
&project_paths,
&extra_roots,

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.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== skills router excerpt ==\n'
sed -n '120,190p' apps/api/src/api/ws/router/skills.rs

printf '\n== search set_enabled_with_extra_roots ==\n'
rg -n "set_enabled_with_extra_roots|spawn_blocking|scan handler|set_enabled" apps/api/src -S

printf '\n== locate SkillManager definition ==\n'
rg -n "struct SkillManager|impl SkillManager|fn set_enabled_with_extra_roots|fn scan" crates apps -S

Repository: AruNi-01/atmos

Length of output: 6676


🏁 Script executed:

true

Repository: AruNi-01/atmos

Length of output: 152


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- apps/api/src/api/ws/router/skills.rs ---'
cat -n apps/api/src/api/ws/router/skills.rs | sed -n '130,190p'

echo '--- search for spawn_blocking in apps/api/src/api/ws/router/skills.rs and related files ---'
rg -n "spawn_blocking|set_enabled_with_extra_roots|scan handler" apps/api/src/api/ws/router/skills.rs apps/api/src -S

echo '--- locate SkillManager method definition ---'
rg -n "fn set_enabled_with_extra_roots|impl SkillManager|struct SkillManager" crates apps -S

Repository: AruNi-01/atmos

Length of output: 4864


🏁 Script executed:

#!/bin/bash
set -euo pipefail

git ls-files 'apps/api/src/api/ws/router/skills.rs' 'crates/**' | sed -n '1,40p'

Repository: AruNi-01/atmos

Length of output: 1556


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- crates/core-service/src/service/skill.rs ---'
cat -n crates/core-service/src/service/skill.rs | sed -n '1,220p'

echo '--- crates/core-service/src/service/skill/scanner.rs ---'
cat -n crates/core-service/src/service/skill/scanner.rs | sed -n '1,380p'

Repository: AruNi-01/atmos

Length of output: 24883


Run the skill toggle in spawn_blocking. SkillManager::set_enabled_with_extra_roots is synchronous filesystem work, so calling it directly from this async handler can block Tokio workers on large or slow workspaces. Offload it and propagate the join + service errors.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/api/src/api/ws/router/skills.rs` around lines 144 - 146, Wrap the
synchronous SkillManager::set_enabled_with_extra_roots call in spawn_blocking
within the async handler, moving or cloning the required project_paths and
extra_roots into the blocking closure. Await the JoinHandle and propagate both
join failures and the service error before continuing the handler flow.

Comment on lines +42 to +56
function scopeLabel(
skill: SkillInfo,
t: ReturnType<typeof useTranslations>,
) {
switch (skill.scope) {
case "global":
return t("scope.global");
case "workspace":
return t("scope.workspace");
case "project":
return t("scope.project");
default:
return skill.scope;
}
}

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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

scopeLabel falls back to an untranslated raw scope string.

SkillInfo.scope includes "inside_project" and "system", but the switch only handles global/workspace/project; the default branch returns skill.scope verbatim instead of a translated label.

🌐 Proposed fix
     case "project":
       return t("scope.project");
+    case "inside_project":
+      return t("scope.insideProject");
+    case "system":
+      return t("scope.system");
     default:
       return skill.scope;
As per coding guidelines, "Avoid hardcoded user-facing labels, titles, tooltips, empty states, and error text; use existing i18n lookup patterns."
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function scopeLabel(
skill: SkillInfo,
t: ReturnType<typeof useTranslations>,
) {
switch (skill.scope) {
case "global":
return t("scope.global");
case "workspace":
return t("scope.workspace");
case "project":
return t("scope.project");
default:
return skill.scope;
}
}
function scopeLabel(
skill: SkillInfo,
t: ReturnType<typeof useTranslations>,
) {
switch (skill.scope) {
case "global":
return t("scope.global");
case "workspace":
return t("scope.workspace");
case "project":
return t("scope.project");
case "inside_project":
return t("scope.insideProject");
case "system":
return t("scope.system");
default:
return skill.scope;
}
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/src/features/skills/components/ComposerSkillsControl.tsx` around
lines 42 - 56, Update scopeLabel to handle the inside_project and system
SkillInfo.scope values with their corresponding translation keys, following the
existing t("scope.*") pattern; remove the raw skill.scope fallback so every
supported scope returns a translated label.

Source: Coding guidelines

Comment on lines +43 to +48
case "workspace":
return {
label: "Workspace",
icon: Folder,
className: "bg-muted text-foreground",
};

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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Localize the workspace scope label.

"Workspace" is hardcoded here, so this card renders English in the Chinese locale even though SkillDetail.tsx uses t("scope.workspace") for the same scope. Pass the translator into getScopeMeta and use the localized key.

As per coding guidelines, apps/web/**/*.{ts,tsx} must read user-facing copy with useTranslations(...) and avoid hardcoded user-facing labels.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/src/features/skills/components/InstalledSkillListCard.tsx` around
lines 43 - 48, Update getScopeMeta to accept the translator and replace the
hardcoded workspace label with the localized scope.workspace key, matching
SkillDetail.tsx. Ensure the InstalledSkillListCard path obtains the translator
via useTranslations and passes it into getScopeMeta while preserving the
existing metadata.

Source: Coding guidelines

Comment thread apps/web/src/features/terminal/components/TerminalSideChatModal.tsx Outdated
| M2 | Terminal AI Input exposes the same control. In a project terminal it uses project disable; in a workspace terminal it uses workplace-rooted disable. |
| M3 | Project disable/enable uses the existing Skills Manager move into `project/.atmos/skills/.disabled/...` and stays consistent with the Skills management page. |
| M4 | Workspace disable/enable reuses the same move logic with storage under `workplace/.atmos/skills/.disabled/...`. |
| M5 | Sync-dir symlink and copy placements can both be disabled by moving the workplace-visible skill entry into `.disabled` so Agents no longer discover it. Parent compensated symlinks are materialized as needed so the move does not mutate the project tree. |

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.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Clarify the symlink terminology.

Line [26] should say “parent symlinks in compensated trees” (or define “compensated symlink”) so the requirement is unambiguous.

🧰 Tools
🪛 LanguageTool

[grammar] ~26-~26: Use a hyphen to join words.
Context: ... so Agents no longer discover it. Parent compensated symlinks are materialized as...

(QB_NEW_EN_HYPHEN)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@specs/APP/APP-040_composer-skills-disable/PRD.md` at line 26, Update the M5
requirement to replace “Parent compensated symlinks” with “parent symlinks in
compensated trees,” or define “compensated symlink” before using it, while
preserving the existing behavior describing materialization without mutating the
project tree.

Source: Linters/SAST tools

Comment thread specs/APP/APP-040_composer-skills-disable/TECH.md
Comment thread specs/APP/APP-040_composer-skills-disable/TECH.md Outdated
Comment on lines +3 to +8
## Test strategy

- **Rust unit tests** for workspace disable with copy and parent-symlink compensation,
and for project disable regression.
- **Bun / component tests** optional for popover tip visibility; not required for M1–M5.
- **Manual / agent-browser**: composer + terminal AI Input toggle smoke.

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.

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Complete the executable verification contract.

The plan only says “manual / agent-browser” and marks UI checks pending; it does not provide setup, exact actions/assertions, manual verification steps, regression coverage, or non-coverage. Add those details, including the required Agent Browser skill/setup procedure and a not_run outcome when setup is unavailable.

As per coding guidelines, TEST.md must include test strategy, coverage and execution maps, scenarios, exploratory checks, regression checklist, acceptance criteria, manual verification steps, non-coverage, and post-run Coverage Status.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@specs/APP/APP-040_composer-skills-disable/TEST.md` around lines 3 - 8, Expand
the TEST.md test plan beyond the current “manual / agent-browser” note to
include test strategy, coverage and execution maps, concrete scenarios with
setup/actions/assertions, exploratory checks, regression checklist, acceptance
criteria, manual verification steps, and explicit non-coverage. Document the
required Agent Browser skill/setup procedure and record a not_run outcome when
setup is unavailable, then add a post-run Coverage Status section summarizing
execution results.

Source: Coding guidelines

Comment thread specs/APP/APP-040_composer-skills-disable/TEST.md Outdated
@github-actions

github-actions Bot commented Jul 22, 2026 •

Copy link
Copy Markdown

E2E report (expired)

This report has been superseded by a newer CI - E2E run.

Field Value
Superseded by run 29909594309
Previous HTML report Open report

Let users toggle skills from slash commands with workplace-local disable for
sync dirs, skip SKILL_DISABLED markers in scans, and add How It Work docs.
@github-actions

github-actions Bot commented Jul 22, 2026 •

Copy link
Copy Markdown

E2E report (expired)

This report has been superseded by a newer CI - E2E run.

Field Value
Superseded by run 29917348797
Previous HTML report Open report

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

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/docs/content/docs/`(app)/how-it-works/meta.json:
- Around line 1-3: Normalize the How It Works navigation metadata across all
three sites: in apps/docs/content/docs/(app)/how-it-works/meta.json, update the
child title to “How It Works”; in apps/docs/content/docs/(app)/meta.json, use
the separator “---How It Works---”; and in
apps/docs/content/docs/(app)/meta.zh.json, use “---工作原理---” while preserving the
English slug.

In `@apps/web/src/features/skills/lib/skill-disable-protocol.ts`:
- Around line 40-46: Update stripSkillDisableSession so whitespace normalization
is limited to the seam created by removing SKILL_DISABLE_PROTOCOL, preserving
all intentional whitespace elsewhere in text. Keep the existing behavior for
prompts without the protocol and continue trimming only the seam’s leading
spaces plus any resulting trailing whitespace.

In `@specs/APP/APP-040_composer-skills-disable/BRAINSTORM.md`:
- Around line 18-22: Update the goal in the specification to make recreating the
live skill directory with SKILL_DISABLED.md mandatory, matching the selected
Option D and final decision. Remove the “optional” wording and state that
alternatives omitting the marker are rejected, while preserving the existing
disabled-storage and entrypoint-removal requirements.

In `@specs/APP/APP-040_composer-skills-disable/TEST.md`:
- Around line 74-85: Update the Acceptance criteria checklist in TEST.md to
include S6, explicitly requiring that disabled skills in the slash insert list
display a Disabled badge and cannot be selected as skill chips. Keep the
existing S1–S3, M6, slash wiring, and project toggle criteria unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f48e9116-cee0-4fe3-b082-fe80f7a2025a

📥 Commits

Reviewing files that changed from the base of the PR and between b87be13 and f2773e9.

📒 Files selected for processing (36)
  • apps/docs/content/docs/(app)/features/skill-management.mdx
  • apps/docs/content/docs/(app)/features/skill-management.zh.mdx
  • apps/docs/content/docs/(app)/how-it-works/dynamic-skills.mdx
  • apps/docs/content/docs/(app)/how-it-works/dynamic-skills.zh.mdx
  • apps/docs/content/docs/(app)/how-it-works/meta.json
  • apps/docs/content/docs/(app)/how-it-works/meta.zh.json
  • apps/docs/content/docs/(app)/meta.json
  • apps/docs/content/docs/(app)/meta.zh.json
  • apps/web/messages/en.json
  • apps/web/messages/zh.json
  • apps/web/src/features/canvas/components/CanvasTerminalCard.tsx
  • apps/web/src/features/skills/hooks/use-composer-disable-skills.ts
  • apps/web/src/features/skills/lib/skill-disable-protocol.ts
  • apps/web/src/features/terminal/components/TerminalAgentInputOverlay.tsx
  • apps/web/src/features/terminal/components/TerminalAgentInputPopovers.tsx
  • apps/web/src/features/terminal/components/TerminalAgentInputShell.tsx
  • apps/web/src/features/terminal/components/TerminalSideChatLayer.tsx
  • apps/web/src/features/terminal/components/TerminalSideChatModal.tsx
  • apps/web/src/features/terminal/components/terminal-mosaic-scoped-pane-window.tsx
  • apps/web/src/features/terminal/components/terminal-mosaic-workspace-pane-window.tsx
  • apps/web/src/features/terminal/hooks/use-terminal-side-chats.tsx
  • apps/web/src/features/welcome/components/PromptComposer.tsx
  • apps/web/src/features/welcome/components/SlashCommandPopover.tsx
  • apps/web/src/features/welcome/components/WelcomeComposerCard.tsx
  • apps/web/src/features/welcome/components/WelcomePage.tsx
  • apps/web/src/features/welcome/hooks/use-welcome-slash-navigation.ts
  • apps/web/src/features/welcome/hooks/use-welcome-slash-search.ts
  • apps/web/src/features/welcome/lib/slash-skill-context.ts
  • crates/core-service/src/service/skill.rs
  • crates/core-service/src/service/skill/scanner.rs
  • crates/core-service/src/service/skill/support.rs
  • crates/core-service/src/service/skill/tests.rs
  • specs/APP/APP-040_composer-skills-disable/BRAINSTORM.md
  • specs/APP/APP-040_composer-skills-disable/PRD.md
  • specs/APP/APP-040_composer-skills-disable/TECH.md
  • specs/APP/APP-040_composer-skills-disable/TEST.md
🚧 Files skipped from review as they are similar to previous changes (7)
  • apps/web/src/features/terminal/components/terminal-mosaic-workspace-pane-window.tsx
  • specs/APP/APP-040_composer-skills-disable/TECH.md
  • crates/core-service/src/service/skill/scanner.rs
  • apps/web/messages/zh.json
  • crates/core-service/src/service/skill/tests.rs
  • crates/core-service/src/service/skill.rs
  • crates/core-service/src/service/skill/support.rs

Comment thread apps/docs/content/docs/(app)/how-it-works/meta.json
Comment on lines +40 to +46
export function stripSkillDisableSession(text: string): string {
const idx = text.indexOf(SKILL_DISABLE_PROTOCOL);
if (idx < 0) return text;
const before = text.slice(0, idx);
const after = text.slice(idx + SKILL_DISABLE_PROTOCOL.length).replace(/^[\u00A0 ]+/, "");
return `${before}${after}`.replace(/[ \u00A0]{2,}/g, " ").trimEnd();
}

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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

stripSkillDisableSession collapses whitespace across the entire prompt.

The final .replace(/[ \u00A0]{2,}/g, " ") runs over the whole string, so when the disable chip is still present at submit time (a common case right after toggling skills), any intentional runs of 2+ spaces in the user's prompt — indented code, aligned text, markdown — get flattened to a single space. Only the seam left by removing the token needs normalizing.

🐛 Proposed fix to normalize only the removal seam
 export function stripSkillDisableSession(text: string): string {
   const idx = text.indexOf(SKILL_DISABLE_PROTOCOL);
   if (idx < 0) return text;
-  const before = text.slice(0, idx);
+  const before = text.slice(0, idx).replace(/[ \u00A0]+$/, "");
   const after = text.slice(idx + SKILL_DISABLE_PROTOCOL.length).replace(/^[\u00A0 ]+/, "");
-  return `${before}${after}`.replace(/[ \u00A0]{2,}/g, " ").trimEnd();
+  const sep = before && after ? " " : "";
+  return `${before}${sep}${after}`.trimEnd();
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export function stripSkillDisableSession(text: string): string {
const idx = text.indexOf(SKILL_DISABLE_PROTOCOL);
if (idx < 0) return text;
const before = text.slice(0, idx);
const after = text.slice(idx + SKILL_DISABLE_PROTOCOL.length).replace(/^[\u00A0 ]+/, "");
return `${before}${after}`.replace(/[ \u00A0]{2,}/g, " ").trimEnd();
}
export function stripSkillDisableSession(text: string): string {
const idx = text.indexOf(SKILL_DISABLE_PROTOCOL);
if (idx < 0) return text;
const before = text.slice(0, idx).replace(/[ \u00A0]+$/, "");
const after = text.slice(idx + SKILL_DISABLE_PROTOCOL.length).replace(/^[\u00A0 ]+/, "");
const sep = before && after ? " " : "";
return `${before}${sep}${after}`.trimEnd();
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/src/features/skills/lib/skill-disable-protocol.ts` around lines 40 -
46, Update stripSkillDisableSession so whitespace normalization is limited to
the seam created by removing SKILL_DISABLE_PROTOCOL, preserving all intentional
whitespace elsewhere in text. Keep the existing behavior for prompts without the
protocol and continue trimming only the seam’s leading spaces plus any resulting
trailing whitespace.

Comment thread specs/APP/APP-040_composer-skills-disable/BRAINSTORM.md Outdated
Comment thread specs/APP/APP-040_composer-skills-disable/TEST.md
Persist workplace/project disable storage so Atmos can re-enable these
skills from .atmos/skills/.disabled later.
Comment thread apps/web/src/features/canvas/components/CanvasTerminalCard.tsx

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.atmos/skills/.disabled/.agents/skills/agent-browser/SKILL.md:
- Line 4: Update the allowed-tools declaration in the agent-browser skill to
prevent unpinned execution: either replace the npx agent-browser allowance with
a pinned, audited version consistently, including any related global-install
path, or remove the npx agent-browser permission entirely.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6fbb0584-1181-4d5f-9d84-f0591196736d

📥 Commits

Reviewing files that changed from the base of the PR and between f2773e9 and beb4506.

📒 Files selected for processing (19)
  • .atmos/skills/.disabled/.agent/skills/adapt
  • .atmos/skills/.disabled/.agent/skills/animate
  • .atmos/skills/.disabled/.agent/skills/colorize
  • .atmos/skills/.disabled/.agents/skills/adapt/SKILL.md
  • .atmos/skills/.disabled/.agents/skills/agent-browser/SKILL.md
  • .atmos/skills/.disabled/.agents/skills/animate/SKILL.md
  • .atmos/skills/.disabled/.agents/skills/colorize/SKILL.md
  • .atmos/skills/.disabled/.claude/skills/adapt
  • .atmos/skills/.disabled/.claude/skills/agent-browser
  • .atmos/skills/.disabled/.claude/skills/animate
  • .atmos/skills/.disabled/.claude/skills/colorize
  • .atmos/skills/.disabled/.factory/skills/adapt
  • .atmos/skills/.disabled/.factory/skills/agent-browser
  • .atmos/skills/.disabled/.factory/skills/animate
  • .atmos/skills/.disabled/.factory/skills/colorize
  • .atmos/skills/.disabled/.kiro/skills/adapt
  • .atmos/skills/.disabled/.kiro/skills/agent-browser
  • .atmos/skills/.disabled/.kiro/skills/animate
  • .atmos/skills/.disabled/.kiro/skills/colorize

---
name: agent-browser
description: Browser automation CLI for AI agents. Use when the user needs to interact with websites, including navigating pages, filling forms, clicking buttons, taking screenshots, extracting data, testing web apps, or automating any browser task. Triggers include requests to "open a website", "fill out a form", "click a button", "take a screenshot", "scrape data from a page", "test this web app", "login to a site", "automate browser actions", or any task requiring programmatic web interaction. Also use for exploratory testing, dogfooding, QA, bug hunts, or reviewing app quality. Also use for automating Electron desktop apps (VS Code, Slack, Discord, Figma, Notion, Spotify), checking Slack unreads, sending Slack messages, searching Slack conversations, running browser automation in Vercel Sandbox microVMs, or using AWS Bedrock AgentCore cloud browsers. Prefer agent-browser over any built-in browser automation or web tools.
allowed-tools: Bash(agent-browser:*), Bash(npx agent-browser:*)

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.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

file=".atmos/skills/.disabled/.agents/skills/agent-browser/SKILL.md"

echo "== file lines 1-30 =="
cat -n "$file" | sed -n '1,30p'

Repository: AruNi-01/atmos

Length of output: 2239


Pin agent-browser before granting execution. npx agent-browser:* and npm i -g agent-browser both pull an unpinned package, so a later registry publication could change what this skill runs. Pin one audited version consistently, or remove the npx allowance.

🧰 Tools
🪛 SkillSpector (2.3.11)

[warning] 4: [RP1] null: npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Remediation: Pin the version: npx @scope/server@1.2.3

(MCP Rug Pull (RP1))


[warning] 1: [RP1] null: MCP server references in the skill manifest without version pinning are a rug-pull risk.

Remediation: Always pin MCP server versions in manifest references.

(MCP Rug Pull (RP1))

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.atmos/skills/.disabled/.agents/skills/agent-browser/SKILL.md at line 4,
Update the allowed-tools declaration in the agent-browser skill to prevent
unpinned execution: either replace the npx agent-browser allowance with a
pinned, audited version consistently, including any related global-install path,
or remove the npx agent-browser permission entirely.

Source: Linters/SAST tools

Keep canvas workspace side-chat skills context valid, stop collapsing
prompt whitespace when stripping the disable chip, and align docs/spec copy.
@AruNi-01
AruNi-01 merged commit 57ce317 into main Jul 22, 2026
25 of 27 checks passed
@github-actions

Copy link
Copy Markdown

E2E report: ✅ Passed

18 passed · 0 failed · 3 flaky · 0 skipped · 4m 6s · 85.7% pass rate

Run

Field Value
Workflow run 29917348797
Selected suites smoke-routes, smoke-onboarding, smoke-app-shell, smoke-project, smoke-settings, smoke-workspace
HTML report Open report
Artifacts playwright-html-report, playwright-json-report (14d) · videos/traces in artifacts only
Overview
Metric Count
Passed 18
Failed 0
Flaky 3
Skipped 0
Duration 4m 6s
Pass rate 85.7%
By file
Name Passed Failed Flaky Skipped
app-shell-navigation.e2e.ts 1 0 0 0
app-shell-preferences-menu.e2e.ts 1 0 0 0
app-shell-workspace-composer.e2e.ts 1 0 0 0
local-onboarding.e2e.ts 2 0 0 0
private-relay-onboarding.e2e.ts 1 0 0 0
project-context-route.e2e.ts 1 0 1 0
remote-onboarding.e2e.ts 1 0 0 0
route-boot.e2e.ts 7 0 0 0
settings-modal.e2e.ts 2 0 1 0
workspace-sidebar-routes.e2e.ts 1 0 1 0
By project
Name Passed Failed Flaky Skipped
chromium 18 0 3 0

All selected E2E suites passed.

This branch was successfully deployed

1 active deployment
Preview — 896d5521 Deployed Jul 22, 2026 by vercel[bot]
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