Class: Aidp::Execute::ReplMacros

Inherits:
Object
  • Object
show all
Defined in:
lib/aidp/execute/repl_macros.rb

Overview

REPL macros for fine-grained human control during work loops Provides commands for:

  • /pin <file> - Mark files as read-only

  • /focus <dir|glob> - Restrict work scope

  • /split - Divide work into smaller contracts

  • /halt-on <pattern> - Pause on specific test failures

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(project_dir: Dir.pwd) ⇒ ReplMacros

Returns a new instance of ReplMacros.



14
15
16
17
18
19
20
21
22
23
# File 'lib/aidp/execute/repl_macros.rb', line 14

def initialize(project_dir: Dir.pwd)
  @pinned_files = Set.new
  @focus_patterns = []
  @halt_patterns = []
  @split_mode = false
  @project_dir = project_dir
  @current_workstream = nil
  @current_skill = nil
  @commands = register_commands
end

Instance Attribute Details

#current_skillObject (readonly)

Returns the value of attribute current_skill.



12
13
14
# File 'lib/aidp/execute/repl_macros.rb', line 12

def current_skill
  @current_skill
end

#current_workstreamObject (readonly)

Returns the value of attribute current_workstream.



12
13
14
# File 'lib/aidp/execute/repl_macros.rb', line 12

def current_workstream
  @current_workstream
end

#focus_patternsObject (readonly)

Returns the value of attribute focus_patterns.



12
13
14
# File 'lib/aidp/execute/repl_macros.rb', line 12

def focus_patterns
  @focus_patterns
end

#halt_patternsObject (readonly)

Returns the value of attribute halt_patterns.



12
13
14
# File 'lib/aidp/execute/repl_macros.rb', line 12

def halt_patterns
  @halt_patterns
end

#pinned_filesObject (readonly)

Returns the value of attribute pinned_files.



12
13
14
# File 'lib/aidp/execute/repl_macros.rb', line 12

def pinned_files
  @pinned_files
end

#split_modeObject (readonly)

Returns the value of attribute split_mode.



12
13
14
# File 'lib/aidp/execute/repl_macros.rb', line 12

def split_mode
  @split_mode
end

Instance Method Details

#current_skill_objectAidp::Skills::Skill?

Retrieve the current skill object, or nil if none is selected

This method provides access to the full skill object (with content, providers, etc.) for the currently selected skill via ‘/skill use <id>`.

Examples:

repl = ReplMacros.new(project_dir: Dir.pwd)
repl.execute("/skill use repository_analyst")
skill = repl.current_skill_object
puts skill.content if skill  # => skill's markdown content

Returns:



130
131
132
133
134
135
136
137
138
139
140
# File 'lib/aidp/execute/repl_macros.rb', line 130

def current_skill_object
  return nil unless @current_skill

  require_relative "../skills"
  registry = Aidp::Skills::Registry.new(project_dir: @project_dir)
  registry.load_skills
  registry.find(@current_skill)
rescue => e
  Aidp.log_error("repl_macros", "Failed to load current skill object", error: e.message)
  nil
end

#current_workstream_pathObject

Get current workstream path (or project_dir if none)



100
101
102
103
104
105
106
# File 'lib/aidp/execute/repl_macros.rb', line 100

def current_workstream_path
  return @project_dir unless @current_workstream

  require_relative "../worktree"
  ws = Aidp::Worktree.info(slug: @current_workstream, project_dir: @project_dir)
  ws ? ws[:path] : @project_dir
end

#execute(command_line) ⇒ Object

Parse and execute a REPL command Returns { success: boolean, message: string, action: symbol }



27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/aidp/execute/repl_macros.rb', line 27

def execute(command_line)
  return {success: false, message: "Empty command", action: :none} if command_line.nil? || command_line.strip.empty?

  parts = command_line.strip.split(/\s+/)
  command = parts[0]
  args = parts[1..]

  if command.start_with?("/")
    execute_macro(command, args)
  else
    {success: false, message: "Unknown command: #{command}", action: :none}
  end
end

#help(command = nil) ⇒ Object

Get help for a specific command



88
89
90
91
92
93
94
95
96
97
# File 'lib/aidp/execute/repl_macros.rb', line 88

def help(command = nil)
  if command.nil?
    @commands.map { |cmd, info| "#{cmd}: #{info[:description]}" }.join("\n")
  elsif @commands.key?(command)
    info = @commands[command]
    "#{command}: #{info[:description]}\nUsage: #{info[:usage]}\nExample: #{info[:example]}"
  else
    "Unknown command: #{command}"
  end
end

#in_focus?(file_path) ⇒ Boolean

Check if a file matches focus scope

Returns:

  • (Boolean)


47
48
49
50
51
52
# File 'lib/aidp/execute/repl_macros.rb', line 47

def in_focus?(file_path)
  return true if @focus_patterns.empty? # No focus = all files in scope

  normalized = normalize_path(file_path)
  @focus_patterns.any? { |pattern| matches_pattern?(normalized, pattern) }
end

#list_commandsObject

List all available commands



83
84
85
# File 'lib/aidp/execute/repl_macros.rb', line 83

def list_commands
  @commands.keys.sort
end

#pinned?(file_path) ⇒ Boolean

Check if a file is pinned (read-only)

Returns:

  • (Boolean)


42
43
44
# File 'lib/aidp/execute/repl_macros.rb', line 42

def pinned?(file_path)
  @pinned_files.include?(normalize_path(file_path))
end

#reset!Object

Clear all macros



75
76
77
78
79
80
# File 'lib/aidp/execute/repl_macros.rb', line 75

def reset!
  @pinned_files.clear
  @focus_patterns.clear
  @halt_patterns.clear
  @split_mode = false
end

#should_halt?(failure_message) ⇒ Boolean

Check if a test failure should trigger a halt

Returns:

  • (Boolean)


55
56
57
58
59
# File 'lib/aidp/execute/repl_macros.rb', line 55

def should_halt?(failure_message)
  return false if @halt_patterns.empty?

  @halt_patterns.any? { |pattern| failure_message.match?(Regexp.new(pattern, Regexp::IGNORECASE)) }
end

#summaryObject

Get summary of current REPL state



62
63
64
65
66
67
68
69
70
71
72
# File 'lib/aidp/execute/repl_macros.rb', line 62

def summary
  {
    pinned_files: @pinned_files.to_a,
    focus_patterns: @focus_patterns,
    halt_patterns: @halt_patterns,
    split_mode: @split_mode,
    current_workstream: @current_workstream,
    current_skill: @current_skill,
    active_constraints: active_constraints_count
  }
end

#switch_workstream(slug) ⇒ Object

Switch to a workstream (called by external code)



109
110
111
112
113
114
115
116
# File 'lib/aidp/execute/repl_macros.rb', line 109

def switch_workstream(slug)
  require_relative "../worktree"
  ws = Aidp::Worktree.info(slug: slug, project_dir: @project_dir)
  return false unless ws

  @current_workstream = slug
  true
end