ace-overseer 0.20.0 → 0.20.2
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/wfi-sources/ace-overseer.yml +1 -1
- data/CHANGELOG.md +27 -0
- data/README.md +14 -14
- data/docs/usage.md +66 -41
- data/handbook/workflow-instructions/overseer.wf.md +13 -9
- data/handbook/workflow-instructions/roles/lab-coordinator.wf.md +99 -0
- data/handbook/workflow-instructions/roles/project-overseer.wf.md +103 -0
- data/handbook/workflow-instructions/roles/second-commander.wf.md +93 -0
- data/lib/ace/overseer/cli/commands/agents.rb +12 -7
- data/lib/ace/overseer/cli/commands/projects.rb +11 -7
- data/lib/ace/overseer/cli/commands/prompt.rb +44 -16
- data/lib/ace/overseer/cli/commands/prune.rb +51 -123
- data/lib/ace/overseer/cli/commands/review.rb +28 -8
- data/lib/ace/overseer/cli/commands/status.rb +33 -19
- data/lib/ace/overseer/cli/commands/stop.rb +18 -8
- data/lib/ace/overseer/cli/commands/work_on.rb +52 -16
- data/lib/ace/overseer/cli.rb +6 -9
- data/lib/ace/overseer/molecules/launch_request.rb +216 -0
- data/lib/ace/overseer/molecules/original_launch_child.rb +165 -0
- data/lib/ace/overseer/molecules/proposal_tick.rb +37 -9
- data/lib/ace/overseer/molecules/protected_selection.rb +46 -0
- data/lib/ace/overseer/molecules/window_opener.rb +9 -2
- data/lib/ace/overseer/organisms/launch_recovery.rb +65 -0
- data/lib/ace/overseer/organisms/protected_prune.rb +116 -0
- data/lib/ace/overseer/organisms/protected_review.rb +167 -0
- data/lib/ace/overseer/organisms/protected_status.rb +157 -0
- data/lib/ace/overseer/organisms/protected_steering.rb +78 -0
- data/lib/ace/overseer/organisms/protected_work_on.rb +102 -0
- data/lib/ace/overseer/organisms/work_on_orchestrator.rb +4 -5
- data/lib/ace/overseer/version.rb +1 -1
- data/lib/ace/overseer.rb +1 -2
- metadata +50 -13
- data/lib/ace/overseer/cli/commands/prepare.rb +0 -38
- data/lib/ace/overseer/molecules/lab_client.rb +0 -56
- data/lib/ace/overseer/molecules/lab_prune_safety_checker.rb +0 -69
data/lib/ace/overseer/version.rb
CHANGED
data/lib/ace/overseer.rb
CHANGED
|
@@ -24,7 +24,6 @@ require_relative "overseer/atoms/preset_resolver"
|
|
|
24
24
|
require_relative "overseer/atoms/runtime_setting"
|
|
25
25
|
require_relative "overseer/atoms/status_formatter"
|
|
26
26
|
require_relative "overseer/molecules/worktree_provisioner"
|
|
27
|
-
require_relative "overseer/molecules/lab_client"
|
|
28
27
|
require_relative "overseer/molecules/window_opener"
|
|
29
28
|
require_relative "overseer/molecules/assignment_launcher"
|
|
30
29
|
require_relative "overseer/molecules/worktree_context_collector"
|
|
@@ -32,9 +31,9 @@ require_relative "overseer/molecules/preservation_manifest"
|
|
|
32
31
|
require_relative "overseer/molecules/git_preservation_checker"
|
|
33
32
|
require_relative "overseer/molecules/prune_safety_checker"
|
|
34
33
|
require_relative "overseer/molecules/assignment_prune_safety_checker"
|
|
35
|
-
require_relative "overseer/molecules/lab_prune_safety_checker"
|
|
36
34
|
require_relative "overseer/organisms/work_on_orchestrator"
|
|
37
35
|
require_relative "overseer/organisms/status_collector"
|
|
36
|
+
require_relative "overseer/organisms/protected_status"
|
|
38
37
|
require_relative "overseer/organisms/prune_orchestrator"
|
|
39
38
|
require_relative "overseer/cli"
|
|
40
39
|
|
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ace-overseer
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.20.
|
|
4
|
+
version: 0.20.2
|
|
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-10 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: ace-support-cli
|
|
@@ -71,28 +71,28 @@ dependencies:
|
|
|
71
71
|
requirements:
|
|
72
72
|
- - "~>"
|
|
73
73
|
- !ruby/object:Gem::Version
|
|
74
|
-
version:
|
|
74
|
+
version: 0.66.1
|
|
75
75
|
type: :runtime
|
|
76
76
|
prerelease: false
|
|
77
77
|
version_requirements: !ruby/object:Gem::Requirement
|
|
78
78
|
requirements:
|
|
79
79
|
- - "~>"
|
|
80
80
|
- !ruby/object:Gem::Version
|
|
81
|
-
version:
|
|
81
|
+
version: 0.66.1
|
|
82
82
|
- !ruby/object:Gem::Dependency
|
|
83
83
|
name: ace-git
|
|
84
84
|
requirement: !ruby/object:Gem::Requirement
|
|
85
85
|
requirements:
|
|
86
86
|
- - "~>"
|
|
87
87
|
- !ruby/object:Gem::Version
|
|
88
|
-
version: '0.
|
|
88
|
+
version: '0.30'
|
|
89
89
|
type: :runtime
|
|
90
90
|
prerelease: false
|
|
91
91
|
version_requirements: !ruby/object:Gem::Requirement
|
|
92
92
|
requirements:
|
|
93
93
|
- - "~>"
|
|
94
94
|
- !ruby/object:Gem::Version
|
|
95
|
-
version: '0.
|
|
95
|
+
version: '0.30'
|
|
96
96
|
- !ruby/object:Gem::Dependency
|
|
97
97
|
name: ace-git-worktree
|
|
98
98
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -127,14 +127,14 @@ dependencies:
|
|
|
127
127
|
requirements:
|
|
128
128
|
- - "~>"
|
|
129
129
|
- !ruby/object:Gem::Version
|
|
130
|
-
version: '0.
|
|
130
|
+
version: '0.3'
|
|
131
131
|
type: :runtime
|
|
132
132
|
prerelease: false
|
|
133
133
|
version_requirements: !ruby/object:Gem::Requirement
|
|
134
134
|
requirements:
|
|
135
135
|
- - "~>"
|
|
136
136
|
- !ruby/object:Gem::Version
|
|
137
|
-
version: '0.
|
|
137
|
+
version: '0.3'
|
|
138
138
|
- !ruby/object:Gem::Dependency
|
|
139
139
|
name: ace-tmux
|
|
140
140
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -155,14 +155,42 @@ dependencies:
|
|
|
155
155
|
requirements:
|
|
156
156
|
- - "~>"
|
|
157
157
|
- !ruby/object:Gem::Version
|
|
158
|
-
version:
|
|
158
|
+
version: 0.5.1
|
|
159
|
+
type: :runtime
|
|
160
|
+
prerelease: false
|
|
161
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
162
|
+
requirements:
|
|
163
|
+
- - "~>"
|
|
164
|
+
- !ruby/object:Gem::Version
|
|
165
|
+
version: 0.5.1
|
|
166
|
+
- !ruby/object:Gem::Dependency
|
|
167
|
+
name: ace-lab
|
|
168
|
+
requirement: !ruby/object:Gem::Requirement
|
|
169
|
+
requirements:
|
|
170
|
+
- - "~>"
|
|
171
|
+
- !ruby/object:Gem::Version
|
|
172
|
+
version: 0.5.1
|
|
173
|
+
type: :runtime
|
|
174
|
+
prerelease: false
|
|
175
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
176
|
+
requirements:
|
|
177
|
+
- - "~>"
|
|
178
|
+
- !ruby/object:Gem::Version
|
|
179
|
+
version: 0.5.1
|
|
180
|
+
- !ruby/object:Gem::Dependency
|
|
181
|
+
name: ace-review
|
|
182
|
+
requirement: !ruby/object:Gem::Requirement
|
|
183
|
+
requirements:
|
|
184
|
+
- - "~>"
|
|
185
|
+
- !ruby/object:Gem::Version
|
|
186
|
+
version: 0.60.1
|
|
159
187
|
type: :runtime
|
|
160
188
|
prerelease: false
|
|
161
189
|
version_requirements: !ruby/object:Gem::Requirement
|
|
162
190
|
requirements:
|
|
163
191
|
- - "~>"
|
|
164
192
|
- !ruby/object:Gem::Version
|
|
165
|
-
version:
|
|
193
|
+
version: 0.60.1
|
|
166
194
|
- !ruby/object:Gem::Dependency
|
|
167
195
|
name: ace-support-test-helpers
|
|
168
196
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -245,6 +273,9 @@ files:
|
|
|
245
273
|
- exe/ace-overseer
|
|
246
274
|
- handbook/skills/as-overseer/SKILL.md
|
|
247
275
|
- handbook/workflow-instructions/overseer.wf.md
|
|
276
|
+
- handbook/workflow-instructions/roles/lab-coordinator.wf.md
|
|
277
|
+
- handbook/workflow-instructions/roles/project-overseer.wf.md
|
|
278
|
+
- handbook/workflow-instructions/roles/second-commander.wf.md
|
|
248
279
|
- lib/ace/overseer.rb
|
|
249
280
|
- lib/ace/overseer/atoms/preset_resolver.rb
|
|
250
281
|
- lib/ace/overseer/atoms/repo_guard.rb
|
|
@@ -252,7 +283,6 @@ files:
|
|
|
252
283
|
- lib/ace/overseer/atoms/status_formatter.rb
|
|
253
284
|
- lib/ace/overseer/cli.rb
|
|
254
285
|
- lib/ace/overseer/cli/commands/agents.rb
|
|
255
|
-
- lib/ace/overseer/cli/commands/prepare.rb
|
|
256
286
|
- lib/ace/overseer/cli/commands/projects.rb
|
|
257
287
|
- lib/ace/overseer/cli/commands/prompt.rb
|
|
258
288
|
- lib/ace/overseer/cli/commands/prune.rb
|
|
@@ -267,14 +297,21 @@ files:
|
|
|
267
297
|
- lib/ace/overseer/molecules/assignment_launcher.rb
|
|
268
298
|
- lib/ace/overseer/molecules/assignment_prune_safety_checker.rb
|
|
269
299
|
- lib/ace/overseer/molecules/git_preservation_checker.rb
|
|
270
|
-
- lib/ace/overseer/molecules/
|
|
271
|
-
- lib/ace/overseer/molecules/
|
|
300
|
+
- lib/ace/overseer/molecules/launch_request.rb
|
|
301
|
+
- lib/ace/overseer/molecules/original_launch_child.rb
|
|
272
302
|
- lib/ace/overseer/molecules/preservation_manifest.rb
|
|
273
303
|
- lib/ace/overseer/molecules/proposal_tick.rb
|
|
304
|
+
- lib/ace/overseer/molecules/protected_selection.rb
|
|
274
305
|
- lib/ace/overseer/molecules/prune_safety_checker.rb
|
|
275
306
|
- lib/ace/overseer/molecules/window_opener.rb
|
|
276
307
|
- lib/ace/overseer/molecules/worktree_context_collector.rb
|
|
277
308
|
- lib/ace/overseer/molecules/worktree_provisioner.rb
|
|
309
|
+
- lib/ace/overseer/organisms/launch_recovery.rb
|
|
310
|
+
- lib/ace/overseer/organisms/protected_prune.rb
|
|
311
|
+
- lib/ace/overseer/organisms/protected_review.rb
|
|
312
|
+
- lib/ace/overseer/organisms/protected_status.rb
|
|
313
|
+
- lib/ace/overseer/organisms/protected_steering.rb
|
|
314
|
+
- lib/ace/overseer/organisms/protected_work_on.rb
|
|
278
315
|
- lib/ace/overseer/organisms/prune_orchestrator.rb
|
|
279
316
|
- lib/ace/overseer/organisms/status_collector.rb
|
|
280
317
|
- lib/ace/overseer/organisms/work_on_orchestrator.rb
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
module Ace
|
|
3
|
-
module Overseer
|
|
4
|
-
module CLI
|
|
5
|
-
module Commands
|
|
6
|
-
class Prepare < Ace::Support::Cli::Command
|
|
7
|
-
include Ace::Support::Cli::Base
|
|
8
|
-
desc "Prepare a Work through the Lab runtime"
|
|
9
|
-
option :runtime, required: true, desc: "Runtime (lab)"
|
|
10
|
-
option :project, required: true, desc: "Lab project slug"
|
|
11
|
-
option :source, required: true, desc: "Source KIND:ID"
|
|
12
|
-
option :work, required: true, desc: "Work ID"
|
|
13
|
-
option :planner, required: true, desc: "Planner agent ID"
|
|
14
|
-
option :title, required: true, desc: "Reviewed Work title"
|
|
15
|
-
def initialize(client: nil)
|
|
16
|
-
super()
|
|
17
|
-
@client = client || Molecules::LabClient.new
|
|
18
|
-
end
|
|
19
|
-
def call(runtime:, project:, source:, work:, planner:, title:, **)
|
|
20
|
-
raise Ace::Support::Cli::Error, "unsupported runtime: #{runtime}" unless runtime == "lab"
|
|
21
|
-
puts @client.call(
|
|
22
|
-
"work", "prepare", project,
|
|
23
|
-
"--source", source,
|
|
24
|
-
"--work", work,
|
|
25
|
-
"--planner", planner,
|
|
26
|
-
"--title", title,
|
|
27
|
-
json: false
|
|
28
|
-
)
|
|
29
|
-
rescue Ace::Support::Cli::Error
|
|
30
|
-
raise
|
|
31
|
-
rescue => error
|
|
32
|
-
raise Ace::Support::Cli::Error.new(error.message)
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
|
-
end
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "json"
|
|
4
|
-
require "open3"
|
|
5
|
-
|
|
6
|
-
module Ace
|
|
7
|
-
module Overseer
|
|
8
|
-
module Molecules
|
|
9
|
-
class LabClient
|
|
10
|
-
BINARY = "/usr/local/bin/lab"
|
|
11
|
-
|
|
12
|
-
def initialize(runner: Open3)
|
|
13
|
-
@runner = runner
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
def call(*arguments, stdin_data: nil, json: true)
|
|
17
|
-
stdout, stderr, status = @runner.capture3(
|
|
18
|
-
BINARY,
|
|
19
|
-
*arguments.map(&:to_s),
|
|
20
|
-
stdin_data: stdin_data.to_s
|
|
21
|
-
)
|
|
22
|
-
raise Error, stderr.to_s.strip.empty? ? "Lab command failed" : stderr.to_s.strip unless status.success?
|
|
23
|
-
|
|
24
|
-
return stdout unless json
|
|
25
|
-
|
|
26
|
-
JSON.parse(stdout)
|
|
27
|
-
rescue Errno::ENOENT
|
|
28
|
-
raise Error, "Lab runtime unavailable: #{BINARY} is not installed"
|
|
29
|
-
rescue JSON::ParserError => error
|
|
30
|
-
raise Error, "Lab returned invalid JSON: #{error.message}"
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
# Whether this surface can make the no-writer state check and the
|
|
34
|
-
# destruction one atomic operation. The raw CLI cannot: between
|
|
35
|
-
# `work status` and `work destroy` another writer may start. Prune
|
|
36
|
-
# treats the path as unsupported (preserve) unless the adapter
|
|
37
|
-
# guarantees atomicity.
|
|
38
|
-
def supports_atomic_destroy?
|
|
39
|
-
false
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
# The authoritative status entry for one Work, or nil when the Work
|
|
43
|
-
# is absent from the surface. Missing state is a blocking condition
|
|
44
|
-
# for prune — never treated as safe.
|
|
45
|
-
#
|
|
46
|
-
# @param work_id [String] Exact Lab Work ID
|
|
47
|
-
# @return [Hash, nil] Status entry or nil
|
|
48
|
-
def work_entry(work_id)
|
|
49
|
-
data = call("work", "status", "--json")
|
|
50
|
-
works = data.is_a?(Hash) ? Array(data["works"]) : []
|
|
51
|
-
works.find { |entry| entry.is_a?(Hash) && entry["id"].to_s == work_id.to_s }
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
end
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Ace
|
|
4
|
-
module Overseer
|
|
5
|
-
module Molecules
|
|
6
|
-
# Fail-closed Lab Work classification for prune.
|
|
7
|
-
#
|
|
8
|
-
# A Lab Work may only be destroyed when the authoritative Lab surface
|
|
9
|
-
# reports a documented terminal state AND preservation evidence is
|
|
10
|
-
# available (declared destination proof). Active work, unknown states,
|
|
11
|
-
# unreadable state, or missing preservation evidence block the
|
|
12
|
-
# candidate — including under --yes. When the Lab surface cannot supply
|
|
13
|
-
# the state, the path reports blocked rather than assuming safety.
|
|
14
|
-
class LabPruneSafetyChecker
|
|
15
|
-
STATES_KEY = %w[state status].freeze
|
|
16
|
-
TERMINAL_STATES = %w[completed done archived cancelled].freeze
|
|
17
|
-
ACTIVE_STATES = %w[
|
|
18
|
-
running in_flight in-flight in_progress in-progress
|
|
19
|
-
active pending reserved claimed started queued
|
|
20
|
-
].freeze
|
|
21
|
-
|
|
22
|
-
Classification = Struct.new(:safe?, :reason, keyword_init: true)
|
|
23
|
-
|
|
24
|
-
# @param lab_client [LabClient] Lab surface adapter
|
|
25
|
-
# @param work_id [String] Exact Lab Work ID
|
|
26
|
-
# @param preservation_proof [Models::PreservationProof, nil] Proof
|
|
27
|
-
# built from the Work's documented preservation data
|
|
28
|
-
# @return [Classification]
|
|
29
|
-
def check(lab_client:, work_id:, preservation_proof: nil)
|
|
30
|
-
entry = read_entry(lab_client, work_id)
|
|
31
|
-
return classify(false, entry) if entry.is_a?(String)
|
|
32
|
-
|
|
33
|
-
value = STATES_KEY.filter_map { |key| entry[key] }.find { |state| state.is_a?(String) }
|
|
34
|
-
return classify(false, "lab state for #{work_id} is unreadable") if value.nil?
|
|
35
|
-
|
|
36
|
-
normalized = value.strip.downcase
|
|
37
|
-
return classify(false, "lab work #{work_id} is #{normalized} (active writer)") if ACTIVE_STATES.include?(normalized)
|
|
38
|
-
|
|
39
|
-
unless TERMINAL_STATES.include?(normalized)
|
|
40
|
-
return classify(false, "lab work #{work_id} state #{normalized.inspect} is not a documented terminal state")
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
if preservation_proof.nil?
|
|
44
|
-
return classify(false, "no preservation evidence for lab work #{work_id}; " \
|
|
45
|
-
"the Lab surface does not document surviving repo/head/branch data")
|
|
46
|
-
end
|
|
47
|
-
unless preservation_proof.preserved?
|
|
48
|
-
return classify(false, preservation_proof.reason)
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
Classification.new(safe?: true, reason: nil)
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
private
|
|
55
|
-
|
|
56
|
-
def read_entry(lab_client, work_id)
|
|
57
|
-
entry = lab_client.work_entry(work_id)
|
|
58
|
-
entry.nil? ? "lab work #{work_id} not found in authoritative status (missing state)" : entry
|
|
59
|
-
rescue Ace::Overseer::Error => e
|
|
60
|
-
"lab state for #{work_id} is unavailable: #{e.message}"
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
def classify(safe, reason)
|
|
64
|
-
Classification.new(safe?: safe, reason: reason)
|
|
65
|
-
end
|
|
66
|
-
end
|
|
67
|
-
end
|
|
68
|
-
end
|
|
69
|
-
end
|