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.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/.ace-defaults/nav/protocols/wfi-sources/ace-overseer.yml +1 -1
  3. data/CHANGELOG.md +27 -0
  4. data/README.md +14 -14
  5. data/docs/usage.md +66 -41
  6. data/handbook/workflow-instructions/overseer.wf.md +13 -9
  7. data/handbook/workflow-instructions/roles/lab-coordinator.wf.md +99 -0
  8. data/handbook/workflow-instructions/roles/project-overseer.wf.md +103 -0
  9. data/handbook/workflow-instructions/roles/second-commander.wf.md +93 -0
  10. data/lib/ace/overseer/cli/commands/agents.rb +12 -7
  11. data/lib/ace/overseer/cli/commands/projects.rb +11 -7
  12. data/lib/ace/overseer/cli/commands/prompt.rb +44 -16
  13. data/lib/ace/overseer/cli/commands/prune.rb +51 -123
  14. data/lib/ace/overseer/cli/commands/review.rb +28 -8
  15. data/lib/ace/overseer/cli/commands/status.rb +33 -19
  16. data/lib/ace/overseer/cli/commands/stop.rb +18 -8
  17. data/lib/ace/overseer/cli/commands/work_on.rb +52 -16
  18. data/lib/ace/overseer/cli.rb +6 -9
  19. data/lib/ace/overseer/molecules/launch_request.rb +216 -0
  20. data/lib/ace/overseer/molecules/original_launch_child.rb +165 -0
  21. data/lib/ace/overseer/molecules/proposal_tick.rb +37 -9
  22. data/lib/ace/overseer/molecules/protected_selection.rb +46 -0
  23. data/lib/ace/overseer/molecules/window_opener.rb +9 -2
  24. data/lib/ace/overseer/organisms/launch_recovery.rb +65 -0
  25. data/lib/ace/overseer/organisms/protected_prune.rb +116 -0
  26. data/lib/ace/overseer/organisms/protected_review.rb +167 -0
  27. data/lib/ace/overseer/organisms/protected_status.rb +157 -0
  28. data/lib/ace/overseer/organisms/protected_steering.rb +78 -0
  29. data/lib/ace/overseer/organisms/protected_work_on.rb +102 -0
  30. data/lib/ace/overseer/organisms/work_on_orchestrator.rb +4 -5
  31. data/lib/ace/overseer/version.rb +1 -1
  32. data/lib/ace/overseer.rb +1 -2
  33. metadata +50 -13
  34. data/lib/ace/overseer/cli/commands/prepare.rb +0 -38
  35. data/lib/ace/overseer/molecules/lab_client.rb +0 -56
  36. data/lib/ace/overseer/molecules/lab_prune_safety_checker.rb +0 -69
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Ace
4
4
  module Overseer
5
- VERSION = "0.20.0"
5
+ VERSION = "0.20.2"
6
6
  end
7
7
  end
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.0
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-05 00:00:00.000000000 Z
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: '0.64'
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: '0.64'
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.29'
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.29'
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.1'
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.1'
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: '0.4'
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: '0.4'
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/lab_client.rb
271
- - lib/ace/overseer/molecules/lab_prune_safety_checker.rb
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