Class: Agentilda::Unblocker
- Inherits:
-
Object
- Object
- Agentilda::Unblocker
- Defined in:
- lib/agentilda/unblocker.rb
Overview
Draining a plan's blocked.md, and saying what happened.
unblock is the one command a human runs because they know something the
tool cannot observe: an answer has arrived. So it owes them an account of
what it did with it. Four things can happen to a plan named on the command
line, and only one of them is the interesting one:
* the number names no folder,
* the folder is not blocked and there is nothing to drain,
* the folder is blocked, and some, none or all of its questions fold in,
* `blocked.md` is there but numbers nothing `## B<n>`, so no program can
read it at all.
Each is reported differently, because each needs a different thing done next. This object works out which one happened; CLI::Unblock prints it.
Defined Under Namespace
Classes: Outcome, Question, Target
Instance Attribute Summary collapse
- #agent ⇒ Agentilda::Agent readonly
- #root ⇒ String readonly
- #tree ⇒ Agentilda::Tree readonly
Class Method Summary collapse
-
.questions(subject) ⇒ Array<Question>
The questions a folder still names, in the order the file names them.
Instance Method Summary collapse
-
#call(subjects) ⇒ Array<Outcome>
Hand each folder to the agent, one at a time, and read the file back.
- #commit? ⇒ Boolean
-
#initialize(tree:, agent:, executor:, root: nil, commit: false) ⇒ Unblocker
constructor
A new instance of Unblocker.
-
#resolve(tokens) ⇒ Array<Target>
Work out what each number on the command line refers to.
Constructor Details
#initialize(tree:, agent:, executor:, root: nil, commit: false) ⇒ Unblocker
Returns a new instance of Unblocker.
94 95 96 97 98 99 100 |
# File 'lib/agentilda/unblocker.rb', line 94 def initialize(tree:, agent:, executor:, root: nil, commit: false) @tree = tree @agent = agent @executor = executor @root = root || File.dirname(tree.dir) @commit = commit end |
Instance Attribute Details
#agent ⇒ Agentilda::Agent (readonly)
106 107 108 |
# File 'lib/agentilda/unblocker.rb', line 106 def agent @agent end |
#root ⇒ String (readonly)
109 110 111 |
# File 'lib/agentilda/unblocker.rb', line 109 def root @root end |
#tree ⇒ Agentilda::Tree (readonly)
103 104 105 |
# File 'lib/agentilda/unblocker.rb', line 103 def tree @tree end |
Class Method Details
.questions(subject) ⇒ Array<Question>
The questions a folder still names, in the order the file names them.
79 80 81 82 83 84 85 86 |
# File 'lib/agentilda/unblocker.rb', line 79 def self.questions(subject) answered = subject.block_answers subject.read("blocked.md").to_s.lines.grep(OPEN_BLOCK).map do |line| number = line[OPEN_BLOCK, 1].to_i Question.new(number:, heading: line.strip.sub(/\A\#+[ \t]*/, ""), answered: answered.include?(number)) end end |
Instance Method Details
#call(subjects) ⇒ Array<Outcome>
Hand each folder to the agent, one at a time, and read the file back.
What the agent claims it did is not evidence. The questions are counted
off disk before and after, so "folded B3" means the heading is gone from
blocked.md, not that an agent said so.
146 147 148 149 150 151 152 153 154 155 156 157 |
# File 'lib/agentilda/unblocker.rb', line 146 def call(subjects) return [] if subjects.empty? before = subjects.map { |subject| [subject.feature.ordinal.to_s, self.class.questions(subject)] }.to_h results = UI.concurrently(subjects, headline(subjects), jobs: 1, label: method(:label), fields: method(:log_fields)) do |subject, progress| invoke(subject, &progress) end settle subjects.zip(results).map { |subject, result| outcome(subject, result, before) } end |
#commit? ⇒ Boolean
112 |
# File 'lib/agentilda/unblocker.rb', line 112 def commit? = @commit |
#resolve(tokens) ⇒ Array<Target>
Work out what each number on the command line refers to.
Nothing is rejected here and nothing exits: a token that names no folder is as much a thing the user needs told about as a folder that drained, and stopping at the first bad one hides the rest of the report.
The gate is blocked.md itself, not the folder's emoji. ⭕️ is derived
from the file, so gating on the emoji made the tool circular: a
blocked.md whose questions are not numbered ## B<n> never earns the
emoji, so unblock refused it, so the file could never drain and the
folder could never leave 🟡.
128 129 130 131 132 133 134 135 136 |
# File 'lib/agentilda/unblocker.rb', line 128 def resolve(tokens) tokens.flat_map { |token| token.to_s.split(",") }.map(&:strip).reject(&:empty?).map do |token| subject = tree.find(token) next Target.new(token:, subject: nil, problem: :missing) if subject.nil? next Target.new(token:, subject:, problem: :not_blocked) unless subject.file?("blocked.md") Target.new(token:, subject:, problem: nil) end end |