sxn 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gem_rbs_collection/addressable/2.8/.rbs_meta.yaml +9 -0
- data/.gem_rbs_collection/addressable/2.8/addressable.rbs +62 -0
- data/.gem_rbs_collection/async/2.12/.rbs_meta.yaml +9 -0
- data/.gem_rbs_collection/async/2.12/async.rbs +119 -0
- data/.gem_rbs_collection/async/2.12/kernel.rbs +5 -0
- data/.gem_rbs_collection/async/2.12/manifest.yaml +7 -0
- data/.gem_rbs_collection/bcrypt/3.1/.rbs_meta.yaml +9 -0
- data/.gem_rbs_collection/bcrypt/3.1/bcrypt.rbs +47 -0
- data/.gem_rbs_collection/bcrypt/3.1/manifest.yaml +2 -0
- data/.gem_rbs_collection/bigdecimal/3.1/.rbs_meta.yaml +9 -0
- data/.gem_rbs_collection/bigdecimal/3.1/bigdecimal-math.rbs +119 -0
- data/.gem_rbs_collection/bigdecimal/3.1/bigdecimal.rbs +1630 -0
- data/.gem_rbs_collection/concurrent-ruby/1.1/.rbs_meta.yaml +9 -0
- data/.gem_rbs_collection/concurrent-ruby/1.1/array.rbs +4 -0
- data/.gem_rbs_collection/concurrent-ruby/1.1/executor.rbs +26 -0
- data/.gem_rbs_collection/concurrent-ruby/1.1/hash.rbs +4 -0
- data/.gem_rbs_collection/concurrent-ruby/1.1/map.rbs +65 -0
- data/.gem_rbs_collection/concurrent-ruby/1.1/promises.rbs +249 -0
- data/.gem_rbs_collection/concurrent-ruby/1.1/utility/processor_counter.rbs +5 -0
- data/.gem_rbs_collection/diff-lcs/1.5/.rbs_meta.yaml +9 -0
- data/.gem_rbs_collection/diff-lcs/1.5/diff-lcs.rbs +11 -0
- data/.gem_rbs_collection/listen/3.9/.rbs_meta.yaml +9 -0
- data/.gem_rbs_collection/listen/3.9/listen.rbs +25 -0
- data/.gem_rbs_collection/listen/3.9/listener.rbs +24 -0
- data/.gem_rbs_collection/mini_mime/0.1/.rbs_meta.yaml +9 -0
- data/.gem_rbs_collection/mini_mime/0.1/mini_mime.rbs +14 -0
- data/.gem_rbs_collection/parallel/1.20/.rbs_meta.yaml +9 -0
- data/.gem_rbs_collection/parallel/1.20/parallel.rbs +86 -0
- data/.gem_rbs_collection/rake/13.0/.rbs_meta.yaml +9 -0
- data/.gem_rbs_collection/rake/13.0/manifest.yaml +2 -0
- data/.gem_rbs_collection/rake/13.0/rake.rbs +39 -0
- data/.gem_rbs_collection/rubocop-ast/1.46/.rbs_meta.yaml +9 -0
- data/.gem_rbs_collection/rubocop-ast/1.46/rubocop-ast.rbs +822 -0
- data/.gem_rbs_collection/sqlite3/2.0/.rbs_meta.yaml +9 -0
- data/.gem_rbs_collection/sqlite3/2.0/database.rbs +20 -0
- data/.gem_rbs_collection/sqlite3/2.0/pragmas.rbs +5 -0
- data/.rspec +4 -0
- data/.rubocop.yml +121 -0
- data/.simplecov +51 -0
- data/CHANGELOG.md +49 -0
- data/Gemfile +24 -0
- data/Gemfile.lock +329 -0
- data/LICENSE.txt +21 -0
- data/README.md +225 -0
- data/Rakefile +54 -0
- data/Steepfile +50 -0
- data/bin/sxn +6 -0
- data/lib/sxn/CLI.rb +275 -0
- data/lib/sxn/commands/init.rb +137 -0
- data/lib/sxn/commands/projects.rb +350 -0
- data/lib/sxn/commands/rules.rb +435 -0
- data/lib/sxn/commands/sessions.rb +300 -0
- data/lib/sxn/commands/worktrees.rb +416 -0
- data/lib/sxn/commands.rb +13 -0
- data/lib/sxn/config/config_cache.rb +295 -0
- data/lib/sxn/config/config_discovery.rb +242 -0
- data/lib/sxn/config/config_validator.rb +562 -0
- data/lib/sxn/config.rb +259 -0
- data/lib/sxn/core/config_manager.rb +290 -0
- data/lib/sxn/core/project_manager.rb +307 -0
- data/lib/sxn/core/rules_manager.rb +306 -0
- data/lib/sxn/core/session_manager.rb +336 -0
- data/lib/sxn/core/worktree_manager.rb +281 -0
- data/lib/sxn/core.rb +13 -0
- data/lib/sxn/database/errors.rb +29 -0
- data/lib/sxn/database/session_database.rb +691 -0
- data/lib/sxn/database.rb +24 -0
- data/lib/sxn/errors.rb +76 -0
- data/lib/sxn/rules/base_rule.rb +367 -0
- data/lib/sxn/rules/copy_files_rule.rb +346 -0
- data/lib/sxn/rules/errors.rb +28 -0
- data/lib/sxn/rules/project_detector.rb +871 -0
- data/lib/sxn/rules/rules_engine.rb +485 -0
- data/lib/sxn/rules/setup_commands_rule.rb +307 -0
- data/lib/sxn/rules/template_rule.rb +262 -0
- data/lib/sxn/rules.rb +148 -0
- data/lib/sxn/runtime_validations.rb +96 -0
- data/lib/sxn/security/secure_command_executor.rb +364 -0
- data/lib/sxn/security/secure_file_copier.rb +478 -0
- data/lib/sxn/security/secure_path_validator.rb +258 -0
- data/lib/sxn/security.rb +15 -0
- data/lib/sxn/templates/common/gitignore.liquid +99 -0
- data/lib/sxn/templates/common/session-info.md.liquid +58 -0
- data/lib/sxn/templates/errors.rb +36 -0
- data/lib/sxn/templates/javascript/README.md.liquid +59 -0
- data/lib/sxn/templates/javascript/session-info.md.liquid +206 -0
- data/lib/sxn/templates/rails/CLAUDE.md.liquid +78 -0
- data/lib/sxn/templates/rails/database.yml.liquid +31 -0
- data/lib/sxn/templates/rails/session-info.md.liquid +144 -0
- data/lib/sxn/templates/template_engine.rb +346 -0
- data/lib/sxn/templates/template_processor.rb +279 -0
- data/lib/sxn/templates/template_security.rb +410 -0
- data/lib/sxn/templates/template_variables.rb +713 -0
- data/lib/sxn/templates.rb +28 -0
- data/lib/sxn/ui/output.rb +103 -0
- data/lib/sxn/ui/progress_bar.rb +91 -0
- data/lib/sxn/ui/prompt.rb +116 -0
- data/lib/sxn/ui/table.rb +183 -0
- data/lib/sxn/ui.rb +12 -0
- data/lib/sxn/version.rb +5 -0
- data/lib/sxn.rb +63 -0
- data/rbs_collection.lock.yaml +180 -0
- data/rbs_collection.yaml +39 -0
- data/scripts/test.sh +31 -0
- data/sig/external/liquid.rbs +116 -0
- data/sig/external/thor.rbs +99 -0
- data/sig/external/tty.rbs +71 -0
- data/sig/sxn/cli.rbs +46 -0
- data/sig/sxn/commands/init.rbs +38 -0
- data/sig/sxn/commands/projects.rbs +72 -0
- data/sig/sxn/commands/rules.rbs +95 -0
- data/sig/sxn/commands/sessions.rbs +62 -0
- data/sig/sxn/commands/worktrees.rbs +82 -0
- data/sig/sxn/commands.rbs +6 -0
- data/sig/sxn/config/config_cache.rbs +67 -0
- data/sig/sxn/config/config_discovery.rbs +64 -0
- data/sig/sxn/config/config_validator.rbs +64 -0
- data/sig/sxn/config.rbs +74 -0
- data/sig/sxn/core/config_manager.rbs +67 -0
- data/sig/sxn/core/project_manager.rbs +52 -0
- data/sig/sxn/core/rules_manager.rbs +54 -0
- data/sig/sxn/core/session_manager.rbs +59 -0
- data/sig/sxn/core/worktree_manager.rbs +50 -0
- data/sig/sxn/core.rbs +87 -0
- data/sig/sxn/database/errors.rbs +37 -0
- data/sig/sxn/database/session_database.rbs +151 -0
- data/sig/sxn/database.rbs +83 -0
- data/sig/sxn/errors.rbs +89 -0
- data/sig/sxn/rules/base_rule.rbs +137 -0
- data/sig/sxn/rules/copy_files_rule.rbs +65 -0
- data/sig/sxn/rules/errors.rbs +33 -0
- data/sig/sxn/rules/project_detector.rbs +115 -0
- data/sig/sxn/rules/rules_engine.rbs +118 -0
- data/sig/sxn/rules/setup_commands_rule.rbs +60 -0
- data/sig/sxn/rules/template_rule.rbs +44 -0
- data/sig/sxn/rules.rbs +287 -0
- data/sig/sxn/runtime_validations.rbs +16 -0
- data/sig/sxn/security/secure_command_executor.rbs +63 -0
- data/sig/sxn/security/secure_file_copier.rbs +79 -0
- data/sig/sxn/security/secure_path_validator.rbs +30 -0
- data/sig/sxn/security.rbs +128 -0
- data/sig/sxn/templates/errors.rbs +43 -0
- data/sig/sxn/templates/template_engine.rbs +50 -0
- data/sig/sxn/templates/template_processor.rbs +44 -0
- data/sig/sxn/templates/template_security.rbs +62 -0
- data/sig/sxn/templates/template_variables.rbs +103 -0
- data/sig/sxn/templates.rbs +104 -0
- data/sig/sxn/ui/output.rbs +50 -0
- data/sig/sxn/ui/progress_bar.rbs +39 -0
- data/sig/sxn/ui/prompt.rbs +38 -0
- data/sig/sxn/ui/table.rbs +43 -0
- data/sig/sxn/ui.rbs +63 -0
- data/sig/sxn/version.rbs +5 -0
- data/sig/sxn.rbs +29 -0
- metadata +635 -0
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Sxn
|
4
|
+
module Core
|
5
|
+
# Manages session lifecycle and operations
|
6
|
+
class SessionManager
|
7
|
+
@config_manager: ConfigManager
|
8
|
+
@database: Sxn::Database::SessionDatabase
|
9
|
+
|
10
|
+
def initialize: (?ConfigManager? config_manager) -> void
|
11
|
+
|
12
|
+
def create_session: (String name, ?description: String?, ?linear_task: String?) -> Hash[Symbol, untyped]
|
13
|
+
|
14
|
+
def remove_session: (String name, ?force: bool) -> bool
|
15
|
+
|
16
|
+
def list_sessions: (?status: String?, ?limit: Integer, ?filters: Hash[untyped, untyped]?, **untyped options) -> Array[Hash[Symbol, untyped]]
|
17
|
+
|
18
|
+
def get_session: (String name) -> Hash[Symbol, untyped]?
|
19
|
+
|
20
|
+
def use_session: (String name) -> Hash[Symbol, untyped]
|
21
|
+
|
22
|
+
def current_session: () -> Hash[Symbol, untyped]?
|
23
|
+
|
24
|
+
def session_exists?: (String name) -> bool
|
25
|
+
|
26
|
+
def add_worktree_to_session: (String session_name, String project_name, String worktree_path, String branch) -> void
|
27
|
+
|
28
|
+
def remove_worktree_from_session: (String session_name, String project_name) -> void
|
29
|
+
|
30
|
+
def get_session_worktrees: (String session_name) -> Hash[String, Hash[Symbol, untyped]]
|
31
|
+
|
32
|
+
def archive_session: (String name) -> bool
|
33
|
+
|
34
|
+
def activate_session: (String name) -> bool
|
35
|
+
|
36
|
+
def cleanup_old_sessions: (?Integer days_old) -> Integer
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def initialize_database: () -> Sxn::Database::SessionDatabase
|
41
|
+
|
42
|
+
def validate_session_name!: (String name) -> void
|
43
|
+
|
44
|
+
def ensure_sessions_folder_exists!: () -> void
|
45
|
+
|
46
|
+
def format_session_data: (Hash[Symbol, untyped] db_row) -> Hash[Symbol, untyped]
|
47
|
+
|
48
|
+
def update_session_status: (String session_id, String status, **untyped additional_options) -> void
|
49
|
+
|
50
|
+
def update_session_status_by_name: (String name, String status, **untyped additional_options) -> void
|
51
|
+
|
52
|
+
def find_uncommitted_worktrees: (Hash[Symbol, untyped] session) -> Array[String]
|
53
|
+
|
54
|
+
def remove_session_worktrees: (Hash[Symbol, untyped] session) -> void
|
55
|
+
|
56
|
+
def find_parent_repository: (String worktree_path) -> String?
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Sxn
|
4
|
+
module Core
|
5
|
+
# Manages git worktree operations
|
6
|
+
class WorktreeManager
|
7
|
+
@config_manager: ConfigManager
|
8
|
+
@session_manager: SessionManager
|
9
|
+
@project_manager: ProjectManager
|
10
|
+
|
11
|
+
def initialize: (?ConfigManager? config_manager, ?SessionManager? session_manager) -> void
|
12
|
+
|
13
|
+
def add_worktree: (String project_name, ?String? branch, ?session_name: String?) -> Hash[Symbol, untyped]
|
14
|
+
|
15
|
+
def remove_worktree: (String project_name, ?session_name: String?) -> bool
|
16
|
+
|
17
|
+
def list_worktrees: (?session_name: String?) -> Array[Hash[Symbol, untyped]]
|
18
|
+
|
19
|
+
def get_worktree: (String project_name, ?session_name: String?) -> Hash[Symbol, untyped]?
|
20
|
+
|
21
|
+
# Check if a worktree exists for a project
|
22
|
+
def worktree_exists?: (String project_name, ?session_name: String?) -> bool
|
23
|
+
|
24
|
+
# Get the path to a worktree for a project
|
25
|
+
def worktree_path: (String project_name, ?session_name: String?) -> String?
|
26
|
+
|
27
|
+
# Validate worktree name (expected by tests)
|
28
|
+
def validate_worktree_name: (String name) -> bool
|
29
|
+
|
30
|
+
# Execute git command (mock point for tests)
|
31
|
+
def execute_git_command: (*untyped) -> bool
|
32
|
+
|
33
|
+
def validate_worktree: (String project_name, ?session_name: String?) -> Hash[Symbol, untyped]
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def create_git_worktree: (String project_path, String worktree_path, String branch) -> void
|
38
|
+
|
39
|
+
def remove_git_worktree: (String project_path, String worktree_path) -> void
|
40
|
+
|
41
|
+
def remove_git_worktree_by_path: (String worktree_path) -> void
|
42
|
+
|
43
|
+
def get_worktree_status: (String path) -> String
|
44
|
+
|
45
|
+
def valid_git_worktree?: (String path) -> bool
|
46
|
+
|
47
|
+
def check_git_status: (String path) -> Array[String]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
data/sig/sxn/core.rbs
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
module Sxn
|
2
|
+
module Core
|
3
|
+
class SessionManager
|
4
|
+
@config: Hash[String, untyped]
|
5
|
+
@database: Database::SessionDatabase
|
6
|
+
@worktree_manager: WorktreeManager
|
7
|
+
@rules_manager: RulesManager
|
8
|
+
|
9
|
+
def initialize: (?config: Hash[String, untyped]?) -> void
|
10
|
+
def create: (String session_name, ?Hash[String, untyped] options) -> Hash[String, untyped]
|
11
|
+
def list: (?status: Symbol?) -> Array[Hash[String, untyped]]
|
12
|
+
def get: (String session_name) -> Hash[String, untyped]?
|
13
|
+
def update: (String session_name, Hash[String, untyped] attributes) -> void
|
14
|
+
def delete: (String session_name) -> void
|
15
|
+
def exists?: (String session_name) -> bool
|
16
|
+
def active_sessions: () -> Array[Hash[String, untyped]]
|
17
|
+
def activate: (String session_name) -> void
|
18
|
+
def deactivate: (String session_name) -> void
|
19
|
+
|
20
|
+
private
|
21
|
+
def validate_session_name: (String name) -> void
|
22
|
+
def create_session_directory: (String session_name, String project_path) -> String
|
23
|
+
def setup_worktree: (String session_name, String project_path) -> void
|
24
|
+
def apply_rules: (String session_name, Hash[String, untyped] options) -> void
|
25
|
+
end
|
26
|
+
|
27
|
+
class WorktreeManager
|
28
|
+
@config: Hash[String, untyped]
|
29
|
+
|
30
|
+
def initialize: (?config: Hash[String, untyped]?) -> void
|
31
|
+
def create: (String name, String source_path, ?String? branch) -> String
|
32
|
+
def list: (String project_path) -> Array[Hash[String, untyped]]
|
33
|
+
def delete: (String name, String project_path) -> void
|
34
|
+
def exists?: (String name, String project_path) -> bool
|
35
|
+
def prune: (String project_path) -> void
|
36
|
+
def get_path: (String name, String project_path) -> String?
|
37
|
+
|
38
|
+
private
|
39
|
+
def validate_git_repository: (String path) -> void
|
40
|
+
def execute_git_command: (String path, String command) -> String
|
41
|
+
def parse_worktree_list: (String output) -> Array[Hash[String, untyped]]
|
42
|
+
end
|
43
|
+
|
44
|
+
class ProjectManager
|
45
|
+
@config: Hash[String, untyped]
|
46
|
+
@database: Database::SessionDatabase
|
47
|
+
|
48
|
+
def initialize: (?config: Hash[String, untyped]?) -> void
|
49
|
+
def add: (String name, String path, ?Hash[String, untyped] options) -> void
|
50
|
+
def remove: (String name) -> void
|
51
|
+
def list: () -> Array[Hash[String, untyped]]
|
52
|
+
def get: (String name) -> Hash[String, untyped]?
|
53
|
+
def update: (String name, Hash[String, untyped] attributes) -> void
|
54
|
+
def exists?: (String name) -> bool
|
55
|
+
def detect_type: (String path) -> Symbol
|
56
|
+
|
57
|
+
private
|
58
|
+
def validate_project_path: (String path) -> void
|
59
|
+
def detect_project_type: (String path) -> Symbol
|
60
|
+
def load_project_config: (String path) -> Hash[String, untyped]
|
61
|
+
end
|
62
|
+
|
63
|
+
class RulesManager
|
64
|
+
@config: Hash[String, untyped]
|
65
|
+
@rules: Array[Rules::BaseRule]
|
66
|
+
|
67
|
+
def initialize: (?config: Hash[String, untyped]?) -> void
|
68
|
+
def add_rule: (Rules::BaseRule rule) -> void
|
69
|
+
def remove_rule: (String rule_name) -> void
|
70
|
+
def apply: (String session_name, Hash[String, untyped] context) -> void
|
71
|
+
def list: () -> Array[Hash[String, untyped]]
|
72
|
+
def get: (String rule_name) -> Rules::BaseRule?
|
73
|
+
def enabled_rules: () -> Array[Rules::BaseRule]
|
74
|
+
def disabled_rules: () -> Array[Rules::BaseRule]
|
75
|
+
|
76
|
+
private
|
77
|
+
def load_rules: () -> Array[Rules::BaseRule]
|
78
|
+
def execute_rule: (Rules::BaseRule rule, Hash[String, untyped] context) -> void
|
79
|
+
def handle_rule_error: (StandardError error, Rules::BaseRule rule) -> void
|
80
|
+
end
|
81
|
+
|
82
|
+
class ConfigManager
|
83
|
+
# Alias to Config::ConfigManager
|
84
|
+
include Config
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# TypeScript RBS for Sxn::Database errors
|
2
|
+
|
3
|
+
module Sxn
|
4
|
+
module Database
|
5
|
+
# Base error class for all database-related errors
|
6
|
+
class Error < ::Sxn::Error
|
7
|
+
end
|
8
|
+
|
9
|
+
# Raised when trying to create a session with a name that already exists
|
10
|
+
class DuplicateSessionError < Error
|
11
|
+
end
|
12
|
+
|
13
|
+
# Raised when trying to access a session that doesn't exist
|
14
|
+
class SessionNotFoundError < Error
|
15
|
+
end
|
16
|
+
|
17
|
+
# Raised when concurrent updates conflict (optimistic locking)
|
18
|
+
class ConflictError < Error
|
19
|
+
end
|
20
|
+
|
21
|
+
# Raised when database schema migration fails
|
22
|
+
class MigrationError < Error
|
23
|
+
end
|
24
|
+
|
25
|
+
# Raised when database integrity checks fail
|
26
|
+
class IntegrityError < Error
|
27
|
+
end
|
28
|
+
|
29
|
+
# Raised when database connection fails
|
30
|
+
class ConnectionError < Error
|
31
|
+
end
|
32
|
+
|
33
|
+
# Raised when transaction rollback occurs
|
34
|
+
class TransactionError < Error
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,151 @@
|
|
1
|
+
# TypeScript RBS for Sxn::Database::SessionDatabase
|
2
|
+
|
3
|
+
module Sxn
|
4
|
+
module Database
|
5
|
+
class SessionDatabase
|
6
|
+
# Constants
|
7
|
+
SCHEMA_VERSION: Integer
|
8
|
+
DEFAULT_DB_PATH: String
|
9
|
+
VALID_STATUSES: Array[String]
|
10
|
+
|
11
|
+
# Instance variables
|
12
|
+
@db_path: Pathname
|
13
|
+
@config: Hash[Symbol, untyped]
|
14
|
+
@prepared_statements: Hash[Symbol, untyped]
|
15
|
+
@connection: untyped
|
16
|
+
|
17
|
+
# Attributes
|
18
|
+
attr_reader db_path: Pathname
|
19
|
+
attr_reader connection: untyped
|
20
|
+
attr_reader config: Hash[Symbol, untyped]
|
21
|
+
|
22
|
+
# Initialize database connection and ensure schema is current
|
23
|
+
#
|
24
|
+
# @param db_path [String, Pathname, nil] Path to SQLite database file
|
25
|
+
# @param config [Hash] Database configuration options
|
26
|
+
def initialize: (?String? db_path, ?Hash[Symbol, untyped] config) -> void
|
27
|
+
|
28
|
+
# Create a new session with validation and conflict detection
|
29
|
+
def create_session: (Hash[Symbol, untyped] session_data) -> String
|
30
|
+
|
31
|
+
# List sessions with filtering, sorting, and pagination
|
32
|
+
def list_sessions: (?filters: Hash[Symbol, untyped], ?sort: Hash[Symbol, untyped], ?limit: Integer, ?offset: Integer) -> Array[Hash[Symbol, untyped]]
|
33
|
+
|
34
|
+
# Update session data with optimistic locking
|
35
|
+
def update_session: (String session_id, ?Hash[Symbol, untyped] updates, ?expected_version: String?) -> bool
|
36
|
+
|
37
|
+
# Delete session with cascade options
|
38
|
+
def delete_session: (String session_id, ?cascade: bool) -> bool
|
39
|
+
|
40
|
+
# Search sessions with full-text search and filters
|
41
|
+
def search_sessions: (String query, ?filters: Hash[Symbol, untyped], ?limit: Integer) -> Array[Hash[Symbol, untyped]]
|
42
|
+
|
43
|
+
# Get single session by ID
|
44
|
+
def get_session: (String session_id) -> Hash[Symbol, untyped]
|
45
|
+
|
46
|
+
# Get session by name
|
47
|
+
def get_session_by_name: (String name) -> Hash[Symbol, untyped]?
|
48
|
+
|
49
|
+
# Alias for get_session for compatibility
|
50
|
+
alias get_session_by_id get_session
|
51
|
+
|
52
|
+
# Get session statistics
|
53
|
+
def statistics: () -> Hash[Symbol, untyped]
|
54
|
+
|
55
|
+
# Execute database maintenance tasks
|
56
|
+
def maintenance: (?Array[Symbol] tasks) -> Hash[Symbol, untyped]
|
57
|
+
|
58
|
+
# Close database connection and cleanup prepared statements
|
59
|
+
def close: () -> void
|
60
|
+
|
61
|
+
# Update session status
|
62
|
+
def update_session_status: (String name, String status) -> bool
|
63
|
+
|
64
|
+
# Public method to create database tables (expected by tests)
|
65
|
+
def create_tables: () -> void
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
# Default database configuration
|
70
|
+
def default_config: () -> Hash[Symbol, untyped]
|
71
|
+
|
72
|
+
# Resolve database path, creating parent directories if needed
|
73
|
+
def resolve_db_path: (String? path) -> Pathname
|
74
|
+
|
75
|
+
# Ensure parent directory exists for database file
|
76
|
+
def ensure_directory_exists: () -> void
|
77
|
+
|
78
|
+
# Initialize SQLite connection with optimized settings
|
79
|
+
def initialize_connection: () -> void
|
80
|
+
|
81
|
+
# Configure SQLite PRAGMA settings for performance and safety
|
82
|
+
def configure_sqlite_pragmas: () -> void
|
83
|
+
|
84
|
+
# Setup database schema and run migrations
|
85
|
+
def setup_database: () -> void
|
86
|
+
|
87
|
+
# Get current schema version from database
|
88
|
+
def get_schema_version: () -> Integer
|
89
|
+
|
90
|
+
# Set schema version in database
|
91
|
+
def set_schema_version: (Integer version) -> void
|
92
|
+
|
93
|
+
# Create initial database schema with optimized indexes
|
94
|
+
def create_initial_schema: () -> void
|
95
|
+
|
96
|
+
# Run database migrations from old version to current
|
97
|
+
def run_migrations: (Integer from_version) -> void
|
98
|
+
|
99
|
+
# Generate secure, unique session ID
|
100
|
+
def generate_session_id: () -> String
|
101
|
+
|
102
|
+
# Validate session data before creation
|
103
|
+
def validate_session_data!: (Hash[Symbol, untyped] data) -> void
|
104
|
+
|
105
|
+
# Validate session update data
|
106
|
+
def validate_session_updates!: (Hash[Symbol, untyped] updates) -> void
|
107
|
+
|
108
|
+
# Serialize tags array to JSON string
|
109
|
+
def serialize_tags: (Array[String]? tags) -> String?
|
110
|
+
|
111
|
+
# Serialize metadata hash to JSON string
|
112
|
+
def serialize_metadata: (Hash[untyped, untyped]? metadata) -> String?
|
113
|
+
|
114
|
+
# Deserialize session row from database
|
115
|
+
def deserialize_session_row: (Hash[String, untyped] row) -> Hash[Symbol, untyped]
|
116
|
+
|
117
|
+
# Get session directory path
|
118
|
+
def session_directory_path: (String session_name) -> String
|
119
|
+
|
120
|
+
# Build WHERE conditions for filtering
|
121
|
+
def build_where_conditions: (Hash[Symbol, untyped] filters, Array[untyped] params) -> Array[String]
|
122
|
+
|
123
|
+
# Execute query with parameters and return results
|
124
|
+
def execute_query: (String sql, ?Array[untyped] params) -> Array[Hash[String, untyped]]
|
125
|
+
|
126
|
+
# Transaction wrapper with rollback support
|
127
|
+
def with_transaction: [T] () { () -> T } -> T
|
128
|
+
|
129
|
+
# Prepare and cache SQL statements for performance
|
130
|
+
def prepare_statement: (Symbol name, String sql) -> untyped
|
131
|
+
|
132
|
+
# Count total sessions
|
133
|
+
def count_sessions: () -> Integer
|
134
|
+
|
135
|
+
# Count sessions by status
|
136
|
+
def count_sessions_by_status: () -> Hash[String, Integer]
|
137
|
+
|
138
|
+
# Get recent session activity (last 7 days)
|
139
|
+
def recent_session_activity: () -> Integer
|
140
|
+
|
141
|
+
# Get database file size in MB
|
142
|
+
def database_size_mb: () -> Float
|
143
|
+
|
144
|
+
# Delete session worktrees (for cascade deletion)
|
145
|
+
def delete_session_worktrees: (String session_id) -> void
|
146
|
+
|
147
|
+
# Delete session files (for cascade deletion)
|
148
|
+
def delete_session_files: (String session_id) -> void
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
module Sxn
|
2
|
+
module Database
|
3
|
+
# High-performance SQLite-based session storage
|
4
|
+
class SessionDatabase
|
5
|
+
type config_hash = Hash[Symbol, untyped]
|
6
|
+
type session_data_hash = Hash[Symbol, untyped]
|
7
|
+
type statistics_hash = Hash[Symbol, untyped]
|
8
|
+
type filters_hash = Hash[Symbol, untyped]
|
9
|
+
type sort_hash = Hash[Symbol, untyped]
|
10
|
+
|
11
|
+
attr_reader db_path: Pathname
|
12
|
+
attr_reader connection: SQLite3::Database?
|
13
|
+
attr_reader config: config_hash
|
14
|
+
|
15
|
+
def initialize: (?String? db_path, ?config_hash config) -> void
|
16
|
+
def create_session: (session_data_hash session_data) -> String
|
17
|
+
def list_sessions: (?filters: filters_hash, ?sort: sort_hash, ?limit: Integer, ?offset: Integer) -> Array[Hash[Symbol, untyped]]
|
18
|
+
def update_session: (String session_id, ?session_data_hash updates, ?expected_version: String?) -> bool
|
19
|
+
def delete_session: (String session_id, ?cascade: bool) -> bool
|
20
|
+
def search_sessions: (String query, ?filters: filters_hash, ?limit: Integer) -> Array[Hash[Symbol, untyped]]
|
21
|
+
def get_session: (String session_id) -> Hash[Symbol, untyped]
|
22
|
+
def get_session_by_name: (String name) -> Hash[Symbol, untyped]?
|
23
|
+
def statistics: () -> statistics_hash
|
24
|
+
def maintenance: (?Array[Symbol] tasks) -> Hash[Symbol, String]
|
25
|
+
def close: () -> void
|
26
|
+
def create_tables: () -> void
|
27
|
+
def update_session_status: (String name, String status) -> bool
|
28
|
+
|
29
|
+
def default_config: () -> config_hash
|
30
|
+
def resolve_db_path: (String? path) -> Pathname
|
31
|
+
def ensure_directory_exists: () -> void
|
32
|
+
def initialize_connection: () -> void
|
33
|
+
def configure_sqlite_pragmas: () -> void
|
34
|
+
def setup_database: () -> void
|
35
|
+
def get_schema_version: () -> Integer
|
36
|
+
def set_schema_version: (Integer version) -> void
|
37
|
+
def create_initial_schema: () -> void
|
38
|
+
def run_migrations: (Integer from_version) -> void
|
39
|
+
def generate_session_id: () -> String
|
40
|
+
def validate_session_data!: (session_data_hash data) -> void
|
41
|
+
def validate_session_updates!: (session_data_hash updates) -> void
|
42
|
+
def serialize_tags: (Array[String]? tags) -> String?
|
43
|
+
def serialize_metadata: (Hash[untyped, untyped]? metadata) -> String?
|
44
|
+
def deserialize_session_row: (Hash[String, untyped] row) -> Hash[Symbol, untyped]
|
45
|
+
def session_directory_path: (String session_name) -> String
|
46
|
+
def build_where_conditions: (filters_hash filters, Array[untyped] params) -> Array[String]
|
47
|
+
def execute_query: (String sql, ?Array[untyped] params) -> Array[Hash[String, untyped]]
|
48
|
+
def with_transaction: [T] () { () -> T } -> T
|
49
|
+
def prepare_statement: (Symbol name, String sql) -> SQLite3::Statement
|
50
|
+
def count_sessions: () -> Integer
|
51
|
+
def count_sessions_by_status: () -> Hash[String, Integer]
|
52
|
+
def recent_session_activity: () -> Integer
|
53
|
+
def database_size_mb: () -> Float
|
54
|
+
def delete_session_worktrees: (String session_id) -> void
|
55
|
+
def delete_session_files: (String session_id) -> void
|
56
|
+
end
|
57
|
+
|
58
|
+
# Database errors
|
59
|
+
class Error < Sxn::Error
|
60
|
+
end
|
61
|
+
|
62
|
+
class DuplicateSessionError < Error
|
63
|
+
end
|
64
|
+
|
65
|
+
class SessionNotFoundError < Error
|
66
|
+
end
|
67
|
+
|
68
|
+
class ConflictError < Error
|
69
|
+
end
|
70
|
+
|
71
|
+
class MigrationError < Error
|
72
|
+
end
|
73
|
+
|
74
|
+
class IntegrityError < Error
|
75
|
+
end
|
76
|
+
|
77
|
+
class ConnectionError < Error
|
78
|
+
end
|
79
|
+
|
80
|
+
class TransactionError < Error
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
data/sig/sxn/errors.rbs
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
module Sxn
|
2
|
+
# Base error class for all Sxn errors
|
3
|
+
class Error < ::StandardError
|
4
|
+
def initialize: (?String? message, ?cause: Exception?) -> void
|
5
|
+
def detailed_message: () -> String
|
6
|
+
def user_message: () -> String
|
7
|
+
|
8
|
+
private
|
9
|
+
def format_backtrace: () -> String?
|
10
|
+
end
|
11
|
+
|
12
|
+
# Configuration related errors
|
13
|
+
class ConfigError < Error
|
14
|
+
end
|
15
|
+
|
16
|
+
class ConfigNotFoundError < ConfigError
|
17
|
+
end
|
18
|
+
|
19
|
+
class ConfigValidationError < ConfigError
|
20
|
+
attr_reader errors: Array[String]
|
21
|
+
|
22
|
+
def initialize: (Array[String] errors, ?String? message) -> void
|
23
|
+
end
|
24
|
+
|
25
|
+
# Session related errors
|
26
|
+
class SessionError < Error
|
27
|
+
end
|
28
|
+
|
29
|
+
class SessionNotFoundError < SessionError
|
30
|
+
end
|
31
|
+
|
32
|
+
class SessionAlreadyExistsError < SessionError
|
33
|
+
end
|
34
|
+
|
35
|
+
class SessionActiveError < SessionError
|
36
|
+
end
|
37
|
+
|
38
|
+
# Worktree related errors
|
39
|
+
class WorktreeError < Error
|
40
|
+
end
|
41
|
+
|
42
|
+
class WorktreeNotFoundError < WorktreeError
|
43
|
+
end
|
44
|
+
|
45
|
+
class WorktreeAlreadyExistsError < WorktreeError
|
46
|
+
end
|
47
|
+
|
48
|
+
# Project related errors
|
49
|
+
class ProjectError < Error
|
50
|
+
end
|
51
|
+
|
52
|
+
class ProjectNotFoundError < ProjectError
|
53
|
+
end
|
54
|
+
|
55
|
+
class ProjectAlreadyExistsError < ProjectError
|
56
|
+
end
|
57
|
+
|
58
|
+
# Git related errors
|
59
|
+
class GitError < Error
|
60
|
+
end
|
61
|
+
|
62
|
+
class NotAGitRepositoryError < GitError
|
63
|
+
end
|
64
|
+
|
65
|
+
class GitCommandError < GitError
|
66
|
+
attr_reader command: String
|
67
|
+
attr_reader exit_status: Integer
|
68
|
+
|
69
|
+
def initialize: (String command, Integer exit_status, ?String? message) -> void
|
70
|
+
end
|
71
|
+
|
72
|
+
# File system errors
|
73
|
+
class FileSystemError < Error
|
74
|
+
end
|
75
|
+
|
76
|
+
class PathNotFoundError < FileSystemError
|
77
|
+
end
|
78
|
+
|
79
|
+
class PermissionDeniedError < FileSystemError
|
80
|
+
end
|
81
|
+
|
82
|
+
# Validation errors
|
83
|
+
class ValidationError < Error
|
84
|
+
attr_reader field: String?
|
85
|
+
attr_reader value: untyped
|
86
|
+
|
87
|
+
def initialize: (?String? field, ?untyped value, ?String? message) -> void
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,137 @@
|
|
1
|
+
# TypeScript RBS for Sxn::Rules::BaseRule
|
2
|
+
|
3
|
+
module Sxn
|
4
|
+
module Rules
|
5
|
+
class BaseRule
|
6
|
+
# Rule execution states
|
7
|
+
module States
|
8
|
+
PENDING: Symbol
|
9
|
+
VALIDATING: Symbol
|
10
|
+
VALIDATED: Symbol
|
11
|
+
APPLYING: Symbol
|
12
|
+
APPLIED: Symbol
|
13
|
+
ROLLING_BACK: Symbol
|
14
|
+
ROLLED_BACK: Symbol
|
15
|
+
FAILED: Symbol
|
16
|
+
end
|
17
|
+
|
18
|
+
include States
|
19
|
+
|
20
|
+
# Instance variables
|
21
|
+
@name: String
|
22
|
+
@config: Hash[String, untyped]
|
23
|
+
@project_path: String
|
24
|
+
@session_path: String
|
25
|
+
@dependencies: Array[String]
|
26
|
+
@state: Symbol
|
27
|
+
@changes: Array[RuleChange]
|
28
|
+
@errors: Array[StandardError]
|
29
|
+
@start_time: Time?
|
30
|
+
@end_time: Time?
|
31
|
+
@logger: untyped
|
32
|
+
|
33
|
+
# Attributes
|
34
|
+
attr_reader name: String
|
35
|
+
attr_reader config: Hash[String, untyped]
|
36
|
+
attr_reader project_path: String
|
37
|
+
attr_reader session_path: String
|
38
|
+
attr_reader state: Symbol
|
39
|
+
attr_reader dependencies: Array[String]
|
40
|
+
attr_reader changes: Array[RuleChange]
|
41
|
+
attr_reader errors: Array[StandardError]
|
42
|
+
|
43
|
+
# Initialize a new rule instance
|
44
|
+
def initialize: (untyped arg1, ?untyped arg2, ?untyped arg3, ?untyped arg4, ?dependencies: Array[String]) -> void
|
45
|
+
|
46
|
+
# Validate the rule configuration and dependencies
|
47
|
+
def validate: () -> bool
|
48
|
+
|
49
|
+
# Apply the rule's action
|
50
|
+
def apply: (?Hash[untyped, untyped] context) -> bool
|
51
|
+
|
52
|
+
# Rollback the rule's changes
|
53
|
+
def rollback: () -> bool
|
54
|
+
|
55
|
+
# Check if this rule can be executed (all dependencies are satisfied)
|
56
|
+
def can_execute?: (Array[String] completed_rules) -> bool
|
57
|
+
|
58
|
+
# Get rule execution duration in seconds
|
59
|
+
def duration: () -> Float?
|
60
|
+
|
61
|
+
# Get rule type
|
62
|
+
def type: () -> String
|
63
|
+
|
64
|
+
# Check if rule is required
|
65
|
+
def required?: () -> bool
|
66
|
+
|
67
|
+
# Validate rule configuration (public method expected by tests)
|
68
|
+
def validate_config_hash: (?Hash[String, untyped] config) -> bool
|
69
|
+
|
70
|
+
# Get rule description
|
71
|
+
def description: () -> String
|
72
|
+
|
73
|
+
# Check if rule has been successfully applied
|
74
|
+
def applied?: () -> bool
|
75
|
+
|
76
|
+
# Check if rule has failed
|
77
|
+
def failed?: () -> bool
|
78
|
+
|
79
|
+
# Check if rule can be rolled back
|
80
|
+
def rollbackable?: () -> bool
|
81
|
+
|
82
|
+
# Get a hash representation of the rule for serialization
|
83
|
+
def to_h: () -> Hash[Symbol, untyped]
|
84
|
+
|
85
|
+
private
|
86
|
+
|
87
|
+
# Track a change made by this rule for rollback purposes
|
88
|
+
def track_change: (Symbol type, String target, ?Hash[Symbol, untyped] metadata) -> RuleChange
|
89
|
+
|
90
|
+
# Get the logger instance
|
91
|
+
def logger: () -> untyped
|
92
|
+
|
93
|
+
# Log a message with rule context
|
94
|
+
def log: (Symbol level, String message, ?Hash[Symbol, untyped] metadata) -> void
|
95
|
+
|
96
|
+
private
|
97
|
+
|
98
|
+
# Change the rule state and track timing
|
99
|
+
def change_state!: (Symbol new_state) -> void
|
100
|
+
|
101
|
+
# Validate that required paths exist and are accessible
|
102
|
+
def validate_paths!: () -> void
|
103
|
+
|
104
|
+
# Validate basic rule configuration
|
105
|
+
def validate_config!: () -> void
|
106
|
+
|
107
|
+
# Validate rule dependencies
|
108
|
+
def validate_dependencies!: () -> void
|
109
|
+
|
110
|
+
# Validate rule-specific configuration
|
111
|
+
def validate_rule_specific!: () -> void
|
112
|
+
|
113
|
+
# Rollback all tracked changes in reverse order
|
114
|
+
def rollback_changes!: () -> bool
|
115
|
+
|
116
|
+
# Represents a single change made by a rule
|
117
|
+
class RuleChange
|
118
|
+
@type: Symbol
|
119
|
+
@target: String
|
120
|
+
@metadata: Hash[Symbol, untyped]
|
121
|
+
@timestamp: Time
|
122
|
+
|
123
|
+
attr_reader type: Symbol
|
124
|
+
attr_reader target: String
|
125
|
+
attr_reader metadata: Hash[Symbol, untyped]
|
126
|
+
attr_reader timestamp: Time
|
127
|
+
|
128
|
+
def initialize: (Symbol type, String target, ?Hash[Symbol, untyped] metadata) -> void
|
129
|
+
|
130
|
+
# Rollback this specific change
|
131
|
+
def rollback: () -> void
|
132
|
+
|
133
|
+
def to_h: () -> Hash[Symbol, untyped]
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|