Feature: REPL input modes and persona controls The interactive REPL supports slash commands, shell passthrough, and inline @ reference expansion. Scenario: Slash persona commands create and activate personas Given a temporary REPL config directory When I run the REPL with input lines | line | | /persona create dev --actor local/mock-default | | /persona list | | /persona set dev | | /persona list | Then the REPL mode output should contain "Created persona: dev" And the REPL mode output should contain "Active persona: dev" And the REPL mode output should contain "dev -> local/mock-default" Scenario: Shell mode runs host shell commands Given a temporary REPL config directory When I run the REPL with input lines | line | | !echo hello | Then the REPL mode output should contain "hello" Scenario: Shell mode blocks dangerous commands without confirmation Given a temporary REPL config directory When I run the REPL with input lines | line | | !rm -rf / | | n | Then the REPL mode output should contain "Blocked dangerous shell command." Scenario: @ references are expanded with canonical category prefixes Given a deterministic REPL reference catalog fixture When I expand REPL references for "info @README.md" Then the expanded REPL line should contain "@file:README.md" Scenario: Slash persona shorthand switches active persona Given a temporary REPL config directory When I run the REPL with input lines | line | | /persona create reviewer --actor local/mock-default | | /persona reviewer | Then the REPL mode output should contain "Active persona: reviewer" Scenario: CLI persona model rejects ANSI/control characters in names When I validate CLI persona name "bad\\x1bname" Then CLI persona validation should fail with "path/control" Scenario: CLI persona model preserves color field When I validate CLI persona payload with color "red" Then CLI persona color should be "red" Scenario: Persona export import and delete workflow Given a temporary REPL config directory And a temporary persona export path When I run the REPL with input lines | line | | /persona create dev --actor local/mock-default | | /persona export dev {export_path} | | /persona delete dev | | /persona import {export_path} | | /persona set dev | Then the REPL mode output should contain "Exported persona:" And the REPL mode output should contain "Deleted persona: dev" And the REPL mode output should contain "Imported persona: dev" And the REPL mode output should contain "Active persona: dev" Scenario: Persona create rejects path traversal names Given a temporary REPL config directory When I run the REPL with input lines | line | | /persona create ../../etc/cron.d/evil --actor local/mock-default | Then the REPL mode output should contain "name must not contain path/control separators" Scenario: Persona export rejects absolute path targets Given a temporary REPL config directory And an absolute persona export path When I run the REPL with input lines | line | | /persona create dev --actor local/mock-default | | /persona export dev {export_path} | Then the REPL mode output should contain "Export path must be relative to current working directory" Scenario: Persona export rejects parent directory escape Given a temporary REPL config directory When I run the REPL with input lines | line | | /persona create dev --actor local/mock-default | | /persona export dev ../outside.yaml | Then the REPL mode output should contain "Export path must stay within working directory" Scenario: Persona import rejects absolute path targets Given a temporary REPL config directory And an absolute persona import file path When I run the REPL with input lines | line | | /persona import {absolute_import_path} | Then the REPL mode output should contain "Import path must be relative to current working directory" Scenario: Persona binding is independent per REPL session Given a temporary REPL config directory When I run the REPL with input lines | line | | /persona create dev --actor local/mock-default | | /persona create reviewer --actor local/mock-default | | /session new work | | /session switch work | | /persona set dev | | /session switch default | | /persona set reviewer | | /session list | Then the REPL mode output should contain "work (persona=dev)" And the REPL mode output should contain "default (persona=reviewer)" Scenario: Deleting persona resets all sessions using it Given a temporary REPL config directory When I run the REPL with input lines | line | | /persona create dev --actor local/mock-default | | /session new work | | /session switch work | | /persona set dev | | /session switch default | | /persona set dev | | /persona delete dev | | /session list | Then the REPL mode output should contain "work (persona=default)" And the REPL mode output should contain "default (persona=default)" Scenario: Slash persona commands surface validation and usage errors Given a temporary REPL config directory And an invalid persona import file path When I run the REPL with input lines | line | | /persona set missing | | /persona create dev | | /persona delete default | | /persona import {invalid_import_path} | Then the REPL mode output should contain "Persona not found: missing" And the REPL mode output should contain "Usage: /persona create --actor " And the REPL mode output should contain "Cannot delete default persona." And the REPL mode output should contain "Invalid persona YAML." Scenario: Persona create parser accepts optional fields and validates cycle-order When I parse persona create tokens "/persona create dev --actor local/mock-default --description fast --icon robot --greeting hi --cycle-order 7" Then parsed persona name should be "dev" And parsed persona actor should be "local/mock-default" And parsed persona cycle order should be 7 When I parse persona create tokens "/persona create dev --actor local/mock-default --cycle-order nope" Then persona create parse should fail with "--cycle-order must be an integer" Scenario: Shell helper handles empty, disabled, and timeout paths When I run REPL shell helper with empty command Then REPL shell helper exit code should be 2 And REPL shell helper output should contain "Shell mode requires a command after '!'." When I run REPL shell helper with command "echo hi" and shell disabled Then REPL shell helper exit code should be 2 And REPL shell helper output should contain "Shell mode is disabled by configuration." When I run REPL shell helper with command "echo hi" and subprocess timeout Then REPL shell helper exit code should be 124 And REPL shell helper output should contain "Shell command timed out after 30s." Scenario: Slash command parser reports errors and session usage guidance Given slash command test sessions When I handle slash text that raises parser error Then slash handler exit code should be 2 And slash handler output should contain "Parse error:" When I handle empty slash text Then slash handler exit code should be 2 And slash handler output should contain "Empty slash command." When I handle slash text "session new" Then slash handler exit code should be 2 And slash handler output should contain "Usage:" Scenario: Reference helpers cover catalog, fuzzy, and suggestion branches Given a rich REPL reference fixture When I build REPL reference catalog from fixture Then REPL catalog should include fixture actor tool skill and env entries And REPL catalog should include non-relative walk file path When I evaluate REPL fuzzy and suggestion helpers Then REPL helper evaluation should pass Scenario: Slash helper covers picker and unknown command branches Given slash command test sessions And slash command test registry with personas When I handle picker slash text "persona pick" using input "x" Then slash handler exit code should be 2 And slash handler output should contain "Invalid selection." When I handle picker slash text "persona pick" using input "9" Then slash handler exit code should be 2 And slash handler output should contain "Selection out of range." When I handle picker slash text "persona pick reviewer" using input "1" Then slash handler exit code should be 0 And slash handler output should contain "Active persona: reviewer" When I handle slash text "persona pick zzz" Then slash handler exit code should be 1 And slash handler output should contain "No personas matched 'zzz'." When I handle slash text "persona import" Then slash handler exit code should be 2 And slash handler output should contain "Usage: /persona import " When I handle slash text "session new default" Then slash handler exit code should be 1 And slash handler output should contain "Session already exists: default" When I handle slash text "session switch missing" Then slash handler exit code should be 1 And slash handler output should contain "Session not found: missing" When I handle slash text "session boom" Then slash handler exit code should be 2 And slash handler output should contain "Unknown session command:" When I handle slash text "persona boom" Then slash handler exit code should be 1 And slash handler output should contain "Persona not found: boom" When I handle slash text "foo bar" Then slash handler exit code should be 2 And slash handler output should contain "Unknown slash command:" Scenario: Shell helper prints stderr and returns subprocess code When I run REPL shell helper with command "echo hi" and subprocess stderr "boom" code 7 Then REPL shell helper exit code should be 7 And REPL shell helper output should contain "boom"