b8f9da4cca
CI / benchmark-publish (pull_request) Has been skipped
CI / lint (pull_request) Successful in 16s
CI / build (pull_request) Successful in 28s
CI / quality (pull_request) Successful in 35s
CI / security (pull_request) Successful in 43s
CI / typecheck (pull_request) Successful in 45s
CI / unit_tests (pull_request) Successful in 3m4s
CI / integration_tests (pull_request) Successful in 3m43s
CI / e2e_tests (pull_request) Successful in 3m48s
CI / docker (pull_request) Successful in 55s
CI / coverage (pull_request) Successful in 6m54s
CI / benchmark-regression (pull_request) Successful in 38m2s
Wrap `PersonaRegistry.delete()` with the personas file lock and use race-safe `unlink` handling for concurrent save/delete consistency.
221 lines
11 KiB
Gherkin
221 lines
11 KiB
Gherkin
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 <name> --actor <namespace/name>"
|
|
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 <path>"
|
|
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"
|