ace-git-worktree 0.26.1 → 0.27.1
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 +4 -4
- data/.ace-defaults/nav/protocols/skill-sources/ace-git-worktree.yml +0 -0
- data/.ace-defaults/nav/protocols/wfi-sources/ace-git-worktree.yml +0 -0
- data/CHANGELOG.md +62 -0
- data/LICENSE +0 -0
- data/README.md +0 -0
- data/Rakefile +0 -0
- data/docs/demo/ace-git-worktree-getting-started.gif +0 -0
- data/docs/demo/ace-git-worktree-getting-started.tape.yml +0 -0
- data/docs/demo/fixtures/README.md +0 -0
- data/docs/demo/fixtures/sample.txt +0 -0
- data/docs/getting-started.md +7 -4
- data/docs/handbook.md +0 -0
- data/docs/usage.md +153 -24
- data/handbook/agents/worktree.ag.md +10 -6
- data/handbook/skills/as-git-worktree/SKILL.md +0 -0
- data/handbook/skills/as-git-worktree-cleanup/SKILL.md +0 -0
- data/handbook/skills/as-git-worktree-create/SKILL.md +0 -0
- data/handbook/skills/as-git-worktree-manage/SKILL.md +0 -0
- data/handbook/workflow-instructions/git/worktree-create.wf.md +3 -3
- data/handbook/workflow-instructions/git/worktree-manage.wf.md +6 -6
- data/handbook/workflow-instructions/git/worktree.wf.md +2 -2
- data/lib/ace/git/worktree/atoms/duration_parser.rb +81 -0
- data/lib/ace/git/worktree/atoms/git_command.rb +0 -0
- data/lib/ace/git/worktree/atoms/path_expander.rb +0 -0
- data/lib/ace/git/worktree/atoms/relative_age_formatter.rb +59 -0
- data/lib/ace/git/worktree/atoms/slug_generator.rb +0 -0
- data/lib/ace/git/worktree/atoms/task_id_extractor.rb +20 -1
- data/lib/ace/git/worktree/atoms/text_truncator.rb +67 -0
- data/lib/ace/git/worktree/cli/commands/bootstrap.rb +0 -0
- data/lib/ace/git/worktree/cli/commands/cleanup.rb +0 -0
- data/lib/ace/git/worktree/cli/commands/config.rb +0 -0
- data/lib/ace/git/worktree/cli/commands/create.rb +0 -0
- data/lib/ace/git/worktree/cli/commands/list.rb +29 -8
- data/lib/ace/git/worktree/cli/commands/prune.rb +0 -0
- data/lib/ace/git/worktree/cli/commands/remove.rb +0 -0
- data/lib/ace/git/worktree/cli/commands/shared_helpers.rb +0 -0
- data/lib/ace/git/worktree/cli/commands/switch.rb +0 -0
- data/lib/ace/git/worktree/cli.rb +1 -1
- data/lib/ace/git/worktree/commands/bootstrap_command.rb +0 -0
- data/lib/ace/git/worktree/commands/list_command.rb +90 -94
- data/lib/ace/git/worktree/commands/prune_command.rb +0 -0
- data/lib/ace/git/worktree/commands/remove_command.rb +0 -0
- data/lib/ace/git/worktree/commands/switch_command.rb +0 -0
- data/lib/ace/git/worktree/configuration.rb +0 -0
- data/lib/ace/git/worktree/models/task_index.rb +186 -0
- data/lib/ace/git/worktree/models/worktree_info.rb +52 -3
- data/lib/ace/git/worktree/models/worktree_metadata.rb +0 -0
- data/lib/ace/git/worktree/molecules/bootstrap_executor.rb +0 -0
- data/lib/ace/git/worktree/molecules/cleanup_applier.rb +0 -0
- data/lib/ace/git/worktree/molecules/config_loader.rb +0 -0
- data/lib/ace/git/worktree/molecules/current_task_linker.rb +0 -0
- data/lib/ace/git/worktree/molecules/hook_executor.rb +0 -0
- data/lib/ace/git/worktree/molecules/parent_task_resolver.rb +0 -0
- data/lib/ace/git/worktree/molecules/pr_status_resolver.rb +172 -0
- data/lib/ace/git/worktree/molecules/recent_branch_counter.rb +70 -0
- data/lib/ace/git/worktree/molecules/task_association_resolver.rb +121 -0
- data/lib/ace/git/worktree/molecules/task_fetcher.rb +0 -0
- data/lib/ace/git/worktree/molecules/task_index_builder.rb +121 -0
- data/lib/ace/git/worktree/molecules/task_pusher.rb +0 -0
- data/lib/ace/git/worktree/molecules/task_status_updater.rb +0 -0
- data/lib/ace/git/worktree/molecules/toolchain_truster.rb +0 -0
- data/lib/ace/git/worktree/molecules/worktree_footer_formatter.rb +43 -0
- data/lib/ace/git/worktree/molecules/worktree_lister.rb +22 -93
- data/lib/ace/git/worktree/molecules/worktree_probe.rb +196 -0
- data/lib/ace/git/worktree/molecules/worktree_remover.rb +0 -0
- data/lib/ace/git/worktree/molecules/worktree_table_formatter.rb +241 -0
- data/lib/ace/git/worktree/organisms/worktree_list_report.rb +315 -0
- data/lib/ace/git/worktree/organisms/worktree_manager.rb +22 -20
- data/lib/ace/git/worktree/organisms/worktree_probe_runner.rb +320 -0
- data/lib/ace/git/worktree/version.rb +1 -1
- data/lib/ace/git/worktree.rb +14 -0
- metadata +15 -2
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "json"
|
|
4
|
+
require "timeout"
|
|
5
|
+
require_relative "../molecules/worktree_probe"
|
|
6
|
+
|
|
7
|
+
module Ace
|
|
8
|
+
module Git
|
|
9
|
+
module Worktree
|
|
10
|
+
module Organisms
|
|
11
|
+
# Runs one read-only probe per worktree in isolated child processes.
|
|
12
|
+
#
|
|
13
|
+
# Contract:
|
|
14
|
+
# - one child per worktree, at most {MAX_LIVE_CHILDREN} alive at once;
|
|
15
|
+
# - each child has a hard {PROBE_TIMEOUT} second budget; a timed-out
|
|
16
|
+
# child is killed together with its process group (no orphan `git`);
|
|
17
|
+
# - children never write repository state or the terminal, and results
|
|
18
|
+
# are stored by input index so output order never depends on child
|
|
19
|
+
# completion order;
|
|
20
|
+
# - a failed/timed-out probe yields nil (rendered as `?` by callers);
|
|
21
|
+
# - when `fork` is unavailable, probes run sequentially with the same
|
|
22
|
+
# per-probe timeout and the same result contract.
|
|
23
|
+
class WorktreeProbeRunner
|
|
24
|
+
# Maximum number of live probe children.
|
|
25
|
+
MAX_LIVE_CHILDREN = 16
|
|
26
|
+
|
|
27
|
+
# Per-probe hard timeout in seconds (implementation constant).
|
|
28
|
+
PROBE_TIMEOUT = 5
|
|
29
|
+
|
|
30
|
+
# @param project_root [String, nil] project root for probe task signals
|
|
31
|
+
# @param base_ref [String, nil] primary worktree head for merge-base diffs
|
|
32
|
+
# @param probe [Proc, nil] injectable probe callable for tests
|
|
33
|
+
# (receives a worktree, returns a Hash or nil); runs inside the child
|
|
34
|
+
# @param max_children [Integer] maximum live children
|
|
35
|
+
# @param timeout [Numeric] per-probe timeout in seconds
|
|
36
|
+
# @param fork_supported [Boolean, nil] force the sequential fallback
|
|
37
|
+
# when false (nil = detect POSIX fork)
|
|
38
|
+
def initialize(project_root: nil, base_ref: nil, probe: nil,
|
|
39
|
+
max_children: MAX_LIVE_CHILDREN, timeout: PROBE_TIMEOUT, fork_supported: nil)
|
|
40
|
+
@project_root = project_root
|
|
41
|
+
@base_ref = base_ref
|
|
42
|
+
@probe = probe
|
|
43
|
+
@max_children = max_children
|
|
44
|
+
@timeout = timeout
|
|
45
|
+
@fork_supported = fork_supported.nil? ? fork_supported? : fork_supported
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Probe every worktree.
|
|
49
|
+
#
|
|
50
|
+
# @param worktrees [Array<Models::WorktreeInfo>] worktrees in display order
|
|
51
|
+
# @return [Array<Hash, nil>] payload per worktree, aligned with input
|
|
52
|
+
def run(worktrees)
|
|
53
|
+
list = Array(worktrees)
|
|
54
|
+
return [] if list.empty?
|
|
55
|
+
return sequential_all(list) unless @fork_supported
|
|
56
|
+
|
|
57
|
+
begin
|
|
58
|
+
fork_all(list)
|
|
59
|
+
rescue NotImplementedError
|
|
60
|
+
# fork exists but is unavailable in this environment (e.g. a
|
|
61
|
+
# restricted container): fall back to sequential probes.
|
|
62
|
+
@fork_supported = false
|
|
63
|
+
sequential_all(list)
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
private
|
|
68
|
+
|
|
69
|
+
def fork_supported?
|
|
70
|
+
Process.respond_to?(:fork) && !Gem.win_platform?
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# --- Forked pool ---
|
|
74
|
+
|
|
75
|
+
def fork_all(worktrees)
|
|
76
|
+
results = Array.new(worktrees.length)
|
|
77
|
+
pending = worktrees.each_with_index.map { |worktree, index| [index, worktree] }
|
|
78
|
+
active = {}
|
|
79
|
+
|
|
80
|
+
begin
|
|
81
|
+
until pending.empty? && active.empty?
|
|
82
|
+
start_children(pending, active) while active.length < @max_children && !pending.empty?
|
|
83
|
+
break if active.empty?
|
|
84
|
+
|
|
85
|
+
wait_for_results(active, results)
|
|
86
|
+
end
|
|
87
|
+
ensure
|
|
88
|
+
terminate_all(active, results)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
results
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def start_children(pending, active)
|
|
95
|
+
index, worktree = pending.shift
|
|
96
|
+
pipe_read, pipe_write = IO.pipe
|
|
97
|
+
flush_standard_streams
|
|
98
|
+
pid = fork do
|
|
99
|
+
child_process(pipe_read, pipe_write, worktree)
|
|
100
|
+
exit!(0)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
pipe_write.close
|
|
104
|
+
pipe_read.binmode
|
|
105
|
+
active[pid] = {
|
|
106
|
+
index: index,
|
|
107
|
+
pipe: pipe_read,
|
|
108
|
+
buffer: +"",
|
|
109
|
+
deadline: monotonic_now + @timeout
|
|
110
|
+
}
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# Body executed in the forked child. Never raises to the parent and
|
|
114
|
+
# never writes to the inherited terminal.
|
|
115
|
+
def child_process(pipe_read, pipe_write, worktree)
|
|
116
|
+
pipe_read.close
|
|
117
|
+
begin
|
|
118
|
+
Process.setpgid(0, 0)
|
|
119
|
+
rescue StandardError
|
|
120
|
+
# Process group isolation is best effort on exotic platforms.
|
|
121
|
+
end
|
|
122
|
+
begin
|
|
123
|
+
STDOUT.reopen(File::NULL)
|
|
124
|
+
STDERR.reopen(File::NULL)
|
|
125
|
+
rescue StandardError
|
|
126
|
+
nil
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
payload = execute_probe(worktree)
|
|
130
|
+
pipe_write.write(JSON.generate(payload)) if payload
|
|
131
|
+
rescue Exception # rubocop:disable Lint/RescueException
|
|
132
|
+
nil
|
|
133
|
+
ensure
|
|
134
|
+
begin
|
|
135
|
+
pipe_write.close
|
|
136
|
+
rescue StandardError
|
|
137
|
+
nil
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
# Wait for at least one child to finish or for the nearest deadline.
|
|
142
|
+
def wait_for_results(active, results)
|
|
143
|
+
pipes = active.values.map { |job| job[:pipe] }
|
|
144
|
+
nearest_deadline = active.values.map { |job| job[:deadline] }.min
|
|
145
|
+
wait_seconds = [nearest_deadline - monotonic_now, 0].max
|
|
146
|
+
|
|
147
|
+
ready = IO.select(pipes, nil, nil, wait_seconds)
|
|
148
|
+
|
|
149
|
+
if ready.nil?
|
|
150
|
+
expire_timed_out(active, results)
|
|
151
|
+
else
|
|
152
|
+
ready.first.each { |pipe| drain_child_pipe(pipe, active, results) }
|
|
153
|
+
expire_timed_out(active, results)
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
# Read currently available bytes; on EOF parse and reap the child.
|
|
158
|
+
def drain_child_pipe(pipe, active, results)
|
|
159
|
+
job = active.values.find { |candidate| candidate[:pipe] == pipe }
|
|
160
|
+
return unless job
|
|
161
|
+
|
|
162
|
+
loop do
|
|
163
|
+
job[:buffer] << pipe.read_nonblock(65_536)
|
|
164
|
+
rescue IO::WaitReadable
|
|
165
|
+
return
|
|
166
|
+
rescue EOFError
|
|
167
|
+
finish_job(active, job, success: true, results: results)
|
|
168
|
+
return
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def finish_job(active, job, success:, results:)
|
|
173
|
+
pid = active.key(job)
|
|
174
|
+
active.delete(pid) if pid
|
|
175
|
+
|
|
176
|
+
if success
|
|
177
|
+
results[job[:index]] = parse_payload(job[:buffer])
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
begin
|
|
181
|
+
job[:pipe].close unless job[:pipe].closed?
|
|
182
|
+
rescue StandardError
|
|
183
|
+
nil
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
reap(pid) if pid
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
def expire_timed_out(active, results)
|
|
190
|
+
now = monotonic_now
|
|
191
|
+
active.values.each do |job|
|
|
192
|
+
next if job[:deadline] > now
|
|
193
|
+
|
|
194
|
+
pid = active.key(job)
|
|
195
|
+
next unless pid
|
|
196
|
+
|
|
197
|
+
terminate(pid)
|
|
198
|
+
results[job[:index]] = nil
|
|
199
|
+
begin
|
|
200
|
+
job[:pipe].close unless job[:pipe].closed?
|
|
201
|
+
rescue StandardError
|
|
202
|
+
nil
|
|
203
|
+
end
|
|
204
|
+
active.delete(pid)
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
# Kill a child's process group (TERM, then KILL) and reap it.
|
|
209
|
+
def terminate(pid)
|
|
210
|
+
terminate_process_group(pid, "TERM")
|
|
211
|
+
# Give the child a brief chance to exit cleanly.
|
|
212
|
+
deadline = monotonic_now + 0.2
|
|
213
|
+
loop do
|
|
214
|
+
break if reap_nonblocking(pid)
|
|
215
|
+
break if monotonic_now > deadline
|
|
216
|
+
|
|
217
|
+
sleep 0.01
|
|
218
|
+
end
|
|
219
|
+
terminate_process_group(pid, "KILL")
|
|
220
|
+
reap(pid)
|
|
221
|
+
rescue Errno::ESRCH
|
|
222
|
+
nil
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
def terminate_all(active, results)
|
|
226
|
+
active.each do |pid, job|
|
|
227
|
+
terminate(pid)
|
|
228
|
+
results[job[:index]] ||= nil
|
|
229
|
+
end
|
|
230
|
+
active.clear
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
def terminate_process_group(pid, signal)
|
|
234
|
+
Process.kill("-#{signal}", pid)
|
|
235
|
+
rescue Errno::ESRCH
|
|
236
|
+
# Group already gone.
|
|
237
|
+
nil
|
|
238
|
+
rescue StandardError
|
|
239
|
+
begin
|
|
240
|
+
Process.kill(signal, pid)
|
|
241
|
+
rescue StandardError
|
|
242
|
+
nil
|
|
243
|
+
end
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
def reap(pid)
|
|
247
|
+
Process.wait(pid)
|
|
248
|
+
rescue Errno::ECHILD
|
|
249
|
+
nil
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
def reap_nonblocking(pid)
|
|
253
|
+
reaped = Process.wait(pid, Process::WNOHANG)
|
|
254
|
+
!reaped.nil?
|
|
255
|
+
rescue Errno::ECHILD
|
|
256
|
+
true
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
# --- Sequential fallback ---
|
|
260
|
+
|
|
261
|
+
def sequential_all(worktrees)
|
|
262
|
+
worktrees.map do |worktree|
|
|
263
|
+
Timeout.timeout(@timeout) { normalize_payload(execute_probe(worktree)) }
|
|
264
|
+
rescue Timeout::Error, StandardError
|
|
265
|
+
nil
|
|
266
|
+
end
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
# --- Probe execution ---
|
|
270
|
+
|
|
271
|
+
def execute_probe(worktree)
|
|
272
|
+
if @probe
|
|
273
|
+
@probe.call(worktree)
|
|
274
|
+
else
|
|
275
|
+
Molecules::WorktreeProbe.new(project_root: @project_root, base_ref: @base_ref).probe(worktree.path)
|
|
276
|
+
end
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
def parse_payload(buffer)
|
|
280
|
+
return nil if buffer.to_s.strip.empty?
|
|
281
|
+
|
|
282
|
+
normalize_payload(JSON.parse(buffer))
|
|
283
|
+
rescue JSON::ParserError
|
|
284
|
+
nil
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
def normalize_payload(payload)
|
|
288
|
+
return nil unless payload.is_a?(Hash)
|
|
289
|
+
|
|
290
|
+
deep_symbolize(payload)
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
def deep_symbolize(value)
|
|
294
|
+
case value
|
|
295
|
+
when Hash
|
|
296
|
+
value.each_with_object({}) { |(key, item), memo| memo[key.to_sym] = deep_symbolize(item) }
|
|
297
|
+
when Array
|
|
298
|
+
value.map { |item| deep_symbolize(item) }
|
|
299
|
+
else
|
|
300
|
+
value
|
|
301
|
+
end
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
# Flush buffered parent output before forking so children never
|
|
305
|
+
# inherit (and re-emit) unflushed terminal output.
|
|
306
|
+
def flush_standard_streams
|
|
307
|
+
$stdout.flush
|
|
308
|
+
$stderr.flush
|
|
309
|
+
rescue StandardError
|
|
310
|
+
nil
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
def monotonic_now
|
|
314
|
+
Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
315
|
+
end
|
|
316
|
+
end
|
|
317
|
+
end
|
|
318
|
+
end
|
|
319
|
+
end
|
|
320
|
+
end
|
data/lib/ace/git/worktree.rb
CHANGED
|
@@ -184,12 +184,24 @@ module Ace
|
|
|
184
184
|
require_relative "worktree/models/worktree_config"
|
|
185
185
|
require_relative "worktree/models/worktree_info"
|
|
186
186
|
require_relative "worktree/models/worktree_metadata"
|
|
187
|
+
require_relative "worktree/models/task_index"
|
|
187
188
|
|
|
188
189
|
require_relative "worktree/atoms/git_command"
|
|
189
190
|
require_relative "worktree/atoms/path_expander"
|
|
190
191
|
require_relative "worktree/atoms/slug_generator"
|
|
192
|
+
require_relative "worktree/atoms/task_id_extractor"
|
|
193
|
+
require_relative "worktree/atoms/duration_parser"
|
|
194
|
+
require_relative "worktree/atoms/relative_age_formatter"
|
|
195
|
+
require_relative "worktree/atoms/text_truncator"
|
|
191
196
|
|
|
192
197
|
require_relative "worktree/molecules/config_loader"
|
|
198
|
+
require_relative "worktree/molecules/task_index_builder"
|
|
199
|
+
require_relative "worktree/molecules/worktree_probe"
|
|
200
|
+
require_relative "worktree/molecules/task_association_resolver"
|
|
201
|
+
require_relative "worktree/molecules/pr_status_resolver"
|
|
202
|
+
require_relative "worktree/molecules/recent_branch_counter"
|
|
203
|
+
require_relative "worktree/molecules/worktree_table_formatter"
|
|
204
|
+
require_relative "worktree/molecules/worktree_footer_formatter"
|
|
193
205
|
require_relative "worktree/molecules/task_fetcher"
|
|
194
206
|
require_relative "worktree/molecules/pull_request_creator"
|
|
195
207
|
require_relative "worktree/molecules/pull_request_evidence_resolver"
|
|
@@ -203,6 +215,8 @@ module Ace
|
|
|
203
215
|
require_relative "worktree/molecules/hook_executor"
|
|
204
216
|
|
|
205
217
|
require_relative "worktree/organisms/task_worktree_orchestrator"
|
|
218
|
+
require_relative "worktree/organisms/worktree_probe_runner"
|
|
219
|
+
require_relative "worktree/organisms/worktree_list_report"
|
|
206
220
|
require_relative "worktree/organisms/worktree_manager"
|
|
207
221
|
|
|
208
222
|
require_relative "worktree/commands/create_command"
|
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ace-git-worktree
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.27.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Michal Czyz
|
|
8
8
|
bindir: exe
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date: 2026-10-
|
|
10
|
+
date: 2026-10-17 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: ace-support-cli
|
|
@@ -199,10 +199,13 @@ files:
|
|
|
199
199
|
- handbook/workflow-instructions/git/worktree-manage.wf.md
|
|
200
200
|
- handbook/workflow-instructions/git/worktree.wf.md
|
|
201
201
|
- lib/ace/git/worktree.rb
|
|
202
|
+
- lib/ace/git/worktree/atoms/duration_parser.rb
|
|
202
203
|
- lib/ace/git/worktree/atoms/git_command.rb
|
|
203
204
|
- lib/ace/git/worktree/atoms/path_expander.rb
|
|
205
|
+
- lib/ace/git/worktree/atoms/relative_age_formatter.rb
|
|
204
206
|
- lib/ace/git/worktree/atoms/slug_generator.rb
|
|
205
207
|
- lib/ace/git/worktree/atoms/task_id_extractor.rb
|
|
208
|
+
- lib/ace/git/worktree/atoms/text_truncator.rb
|
|
206
209
|
- lib/ace/git/worktree/cli.rb
|
|
207
210
|
- lib/ace/git/worktree/cli/commands/bootstrap.rb
|
|
208
211
|
- lib/ace/git/worktree/cli/commands/cleanup.rb
|
|
@@ -222,6 +225,7 @@ files:
|
|
|
222
225
|
- lib/ace/git/worktree/commands/remove_command.rb
|
|
223
226
|
- lib/ace/git/worktree/commands/switch_command.rb
|
|
224
227
|
- lib/ace/git/worktree/configuration.rb
|
|
228
|
+
- lib/ace/git/worktree/models/task_index.rb
|
|
225
229
|
- lib/ace/git/worktree/models/worktree_config.rb
|
|
226
230
|
- lib/ace/git/worktree/models/worktree_info.rb
|
|
227
231
|
- lib/ace/git/worktree/models/worktree_metadata.rb
|
|
@@ -233,19 +237,28 @@ files:
|
|
|
233
237
|
- lib/ace/git/worktree/molecules/current_task_linker.rb
|
|
234
238
|
- lib/ace/git/worktree/molecules/hook_executor.rb
|
|
235
239
|
- lib/ace/git/worktree/molecules/parent_task_resolver.rb
|
|
240
|
+
- lib/ace/git/worktree/molecules/pr_status_resolver.rb
|
|
236
241
|
- lib/ace/git/worktree/molecules/pull_request_checkout_preparer.rb
|
|
237
242
|
- lib/ace/git/worktree/molecules/pull_request_creator.rb
|
|
238
243
|
- lib/ace/git/worktree/molecules/pull_request_evidence_resolver.rb
|
|
244
|
+
- lib/ace/git/worktree/molecules/recent_branch_counter.rb
|
|
245
|
+
- lib/ace/git/worktree/molecules/task_association_resolver.rb
|
|
239
246
|
- lib/ace/git/worktree/molecules/task_committer.rb
|
|
240
247
|
- lib/ace/git/worktree/molecules/task_fetcher.rb
|
|
248
|
+
- lib/ace/git/worktree/molecules/task_index_builder.rb
|
|
241
249
|
- lib/ace/git/worktree/molecules/task_pusher.rb
|
|
242
250
|
- lib/ace/git/worktree/molecules/task_status_updater.rb
|
|
243
251
|
- lib/ace/git/worktree/molecules/toolchain_truster.rb
|
|
244
252
|
- lib/ace/git/worktree/molecules/worktree_creator.rb
|
|
253
|
+
- lib/ace/git/worktree/molecules/worktree_footer_formatter.rb
|
|
245
254
|
- lib/ace/git/worktree/molecules/worktree_lister.rb
|
|
255
|
+
- lib/ace/git/worktree/molecules/worktree_probe.rb
|
|
246
256
|
- lib/ace/git/worktree/molecules/worktree_remover.rb
|
|
257
|
+
- lib/ace/git/worktree/molecules/worktree_table_formatter.rb
|
|
247
258
|
- lib/ace/git/worktree/organisms/task_worktree_orchestrator.rb
|
|
259
|
+
- lib/ace/git/worktree/organisms/worktree_list_report.rb
|
|
248
260
|
- lib/ace/git/worktree/organisms/worktree_manager.rb
|
|
261
|
+
- lib/ace/git/worktree/organisms/worktree_probe_runner.rb
|
|
249
262
|
- lib/ace/git/worktree/version.rb
|
|
250
263
|
homepage: https://github.com/cs3b/ace
|
|
251
264
|
licenses:
|