feat: sticky agent mode — mode locking + permission-based skill scoping#1725
Merged
Conversation
After a session's first message, the mode is locked to the current group: - Build/Plan form a free-switch group (Tab cycles between them) - All other modes (Compose, etc.) are isolated once entered - /new restores free selection; /session respects existing lock Implementation: - set() for system/programmatic use (unguarded) - userSwitch() for user actions (guarded, shows contextual toast) - move() cycles within allowed group, skips blocked agents - Reactive derivation from lastUserMessage() — no manual lock state
Replace hidden:true with permission system for compose skills: - defaults deny compose:* skills; compose agent allows them - defaults deny plan_enter/plan_exit; build+plan allow (symmetric) - Skill.available() relies on permissions, not hidden flag - Remove composeSkillsBlock() from extract.ts and prompt.ts - Skills appear naturally in system prompt via available(agent) Result: future agents auto-inherit deny rules, compose gets a clean tool/skill list, and the system prompt is stable within a session.
Collaborator
Author
|
@wqymi @MiMoHardFather Check this |
…ary batch() - Verify build/plan deny compose:* skills, compose allows them - Verify non-compose skills remain allowed for all agents - Remove redundant batch() wrapper in move() (single write, no batching needed)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Lock agent mode after the first message in a session, ensuring a stable system prompt (skills + tools) throughout the conversation. Supporting change: replace
hidden: truewith a permission-based scoping system for compose skills and plan tools.Motivation
Mode-switching mid-session causes prefix cache invalidation (the system prompt changes when skills/tools change). This is both a performance cost and a source of confusion — the model's context shifts underneath the user. By locking mode after the first message:
Changes
1. Sticky Mode (TUI)
FREE_SWITCH_GROUP = ["build", "plan"]— can freely switch between theseset()(system) vsuserSwitch()(user) separation — only user actions are guardedlastUserMessage()—/newand/sessionwork correctly without manual lock/unlock2. Permission-Based Skill and Tool Scoping
defaults deny compose:*, compose agent explicitly allowsdefaults deny plan_enter/plan_exit, build+plan allow (symmetric)Skill.available()relies on permissions, nothiddenflagcomposeSkillsBlock()injection — skills appear naturally in the system promptDesign Decisions
set()vsuserSwitch()!!lastUserMessage()move()skips blocked agentsBreaking Changes (need discussion)
FREE_SWITCH_GROUPare treated as isolated. Would need group configuration support.hidden: truedeprecated: Skills relying on hidden must migrate to permission config.plan_enter/plan_exit.Tests
bun typecheck— cleanbun test test/agent/agent.test.ts— 48/48 passbun test test/session/prompt-skill-mention.test.ts— 8/8 passbun test test/permission— 141/141 passOpen Questions
FREE_SWITCH_GROUPbe configurable (e.g., user-defined agents can declare their group)?/unlockescape hatch for power users?Supersedes #1719 (experimental branch, closed).