ace-overseer 0.21.1 → 0.23.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9a94cecc6258f74a611ffb1091359b4a7e2c10709e8a185019929b1a353111ba
4
- data.tar.gz: 50d41733c822af101ef77dc369f4450d5466df43e04a0894b22864328b94ba70
3
+ metadata.gz: fd32b216cc419e55b10e481b3ba442d804050861742f7f126305bc73eb8090da
4
+ data.tar.gz: 335305972f6ae62c855a41376b3ba382c552105fb09b92aa2a5b326186d0da20
5
5
  SHA512:
6
- metadata.gz: d7b93b7a2444123a261351df666dbbb6ff47b16d1972c5e46230cff1418c87c0982ad7adb7309dac7a1f008348f0593042f32168bec1133557b49cc103ac880c
7
- data.tar.gz: a48575ea94be30eeb49f8a0244477b47a3c304328ba2cb6ae71ee2b1a4d0b8d3413c846388a648daa3c875165c2b01d6c18e91ec725f8637cbeef85081d69f03
6
+ metadata.gz: bbb4e556c4a5d54b20d81ff7f106bd51a1330108e72128cdf93e386ababcda033cbe3217b145fd34fdc4ec3a68e77cceab89db69ac193020f6e8e7b66e27d203
7
+ data.tar.gz: 68c9e4d5e29d70d95d31b11d1d6be3dfb963628ba0d380a5f926d1e2d2b876a78946ac9497365fbfafc1263332a584eec0121c13ccacc713e2bdfea1fb904dc1
data/CHANGELOG.md CHANGED
@@ -7,6 +7,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.23.0] - 2026-10-16
11
+
12
+ ### Added
13
+
14
+ - Add explicit ordinary preparation/launch/resume using existing worktree, native pane and provider mechanisms. Preserve original identities and dispatch intent on response loss; use native filesystem watches only as canonical-inspection hints.
15
+
16
+ ### Changed
17
+
18
+ - Follow ace-review 0.61 campaign head-assessment contracts (dependency floor).
19
+
20
+ ## [0.22.0] - 2026-10-16
21
+
22
+ ### Added
23
+
24
+ - Package native continuation duties with ten-minute progress and hourly cleanup audits, exact session restoration, independent project progress and explicit unknown outcomes. Align role workflows with canonical Assign ownership and accepted-head review.
25
+
10
26
  ## [0.21.1] - 2026-10-14
11
27
 
12
28
  ### Changed
data/LICENSE CHANGED
File without changes
data/Rakefile CHANGED
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
data/docs/handbook.md CHANGED
@@ -37,6 +37,12 @@ ace-docs:
37
37
  - Purpose: resolve and review effective delivery presets, workflows, and decision guides, then apply repeatable project-local adaptation while preserving customization
38
38
  - Output: per-asset `CREATED`, `UPDATED`, `KEPT`, or `BLOCKED` evidence plus a repeat-run zero-write check
39
39
 
40
+ ### `wfi://overseer/maintain-continuation`
41
+
42
+ - Path: `handbook/workflow-instructions/overseer/maintain-continuation.wf.md`
43
+ - Purpose: bootstrap native 600-second progress and 3600-second cleanup duties, then restore the exact persisted session without duplicate registration
44
+ - Evidence: real model turn, persisted ace-wake entries, exact-session restart and consumed wake; Assign remains execution owner
45
+
40
46
  ## Related Documentation
41
47
 
42
48
  - [Getting Started](getting-started.md)
data/docs/usage.md CHANGED
@@ -12,6 +12,7 @@ ace-docs:
12
12
  ## Command Surface
13
13
 
14
14
  - `ace-overseer work-on`
15
+ - `ace-overseer ordinary`
15
16
  - `ace-overseer status`
16
17
  - `ace-overseer prune`
17
18
  - `ace-overseer projects`
@@ -54,6 +55,50 @@ observation, never canonical terminal/release or physical cleanup permission.
54
55
  Recovery reports absent/mismatched local inputs separately from original canonical
55
56
  reservation attribution, without upload, reconstruction or retry.
56
57
 
58
+ ## `ace-overseer ordinary`
59
+
60
+ Ordinary execution is explicit and uses the root-selected project's Assign owner.
61
+ `work-on --project` keeps its protected contract and never falls back here.
62
+ The native supervisor prepares each reviewed leaf in its own existing worktree
63
+ and prepared pane, registers exact captured inputs, then launches its explicit
64
+ provider profile:
65
+
66
+ ```sh
67
+ ace-overseer ordinary --operation prepare --project atlas --task 8wr.t.abc --checkout /lab/projects/atlas \
68
+ --provider pi:zai/glm-5.3-flash:high --output /private/ordinary/task-one
69
+ ace-overseer ordinary --operation launch --project atlas --context /private/ordinary/task-one/context.json
70
+ ace-overseer ordinary --operation resume --project atlas --context /private/ordinary/task-one/context.json
71
+ ```
72
+
73
+ Preparation validates the explicit checkout against the installed Git common directory, then uses WorktreeProvisioner, WindowOpener and PreparedWorkBuilder. Project configuration resolves inside the selected checkout/worktree even when the native supervisor runs from another project. The
74
+ provider/model/thinking selection must resolve through the existing LLM builder.
75
+ It retains exact IDs, HEAD, scope and worker pane before registration. If the
76
+ registration reply is lost, inspect canonical status through that original
77
+ context; if registration is absent, replay the original `prepared/request.json`
78
+ with `ace-lab assignment request`. Do not create another preparation to bypass
79
+ uncertainty. Partial preparation errors preserve their files for inspection.
80
+
81
+ Launch verifies the actual current native supervisor against canonical ownership,
82
+ retains a dispatch intent before native send and sends the worker's ordinary
83
+ `/as-assign-drive` entry. Acknowledgement means accepted send, not process start.
84
+ The worker must register its own actual start through the installed owner.
85
+ An existing dispatch intent plus no start stays `dispatch_uncertain`; neither
86
+ launch nor resume sends a second command. `status` and `resume` are read-only
87
+ observations of the original assignment/attempt and current supervisor selection.
88
+
89
+ The returned native `/watch add` command watches a result hint file. Install it
90
+ once in the supervisor session, persist through a harmless turn, then resume the
91
+ exact session without replaying add commands or restoring intentional removals.
92
+ A watch is only a wake hint; canonical `ace-lab assignment drive --operation status`
93
+ and `adopt` decide outcome. Existing progress-audit duties also reconcile lost
94
+ hints. A replaced coordinator first performs explicit canonical supervisor
95
+ adoption as documented in Lab usage; worker identities and requests survive it.
96
+
97
+ For two workers, repeat prepare with two reviewed leaf tasks and separate output
98
+ directories. Verify two distinct panes/attempts, two canonical starts and results,
99
+ and sequential reviewed ordinary merges. This source interface does not claim
100
+ installed watches, real provider turns, review, release or merge acceptance.
101
+
57
102
  ## `ace-overseer status`
58
103
 
59
104
  Show status for active task worktrees.
File without changes
@@ -40,7 +40,7 @@ Read existing project-owned sources before proposing a change:
40
40
  - Current task, Assign, review, release, and delivery records that already own work.
41
41
  - Repository guidance such as `AGENTS.md`, architecture decisions, and delivery docs.
42
42
 
43
- Resolve rather than infer protocol ownership. Run `ace-nav explain <URI>` followed by
43
+ Resolve rather than infer protocol ownership. Run `ace-nav resolve <URI> --why` followed by
44
44
  `ace-nav resolve <URI>` for every applicable `wfi://` workflow and for
45
45
  `guide://delivery-supervision`. Load resolved workflow content with `ace-bundle <URI>`.
46
46
  If the expected project decision guide uses another registered URI, record that URI
@@ -87,21 +87,26 @@ contract. Preserve stronger project requirements. Require these minimum invarian
87
87
 
88
88
  - Worker and implementation-parent terminal behavior remains PR-ready; delivery stays
89
89
  a separate explicit decision scope.
90
- - One canonical Assign tree and attempt/evidence ledger owns state. No second queue,
91
- journal, daemon, timer, or fabricated runtime context is introduced.
90
+ - One canonical Assign tree and attempt/evidence ledger owns state. Local objective queues contain goals, next actions, blockers and references only;
91
+ no duplicate execution state, journal, daemon, timer, or fabricated runtime context is introduced.
92
92
  - Integration decisions record the ordered eligible set, selected entry, every
93
93
  deferred entry with reason, actor, timestamp, evidence references, and policy/plan
94
94
  revision. Completion order is never integration order.
95
95
  - Dependency, candidate head, target head, evidence, authority, or transport movement
96
- triggers a fresh decision. A moved candidate receives fresh relevant tests and an
97
- independent review bound to its new exact head.
96
+ triggers a fresh decision. Require an initial independent review and fresh relevant
97
+ tests. For every moved head, record a delta/context/risk assessment: executed content
98
+ identity may carry review across an identical rebase; minor safe corrections need
99
+ integrator reasoning/tests; material or uncertain changes need independent delta
100
+ review. Patch-id alone cannot carry review. Bind the accepted head to the server-side
101
+ merge guard, and keep formal forge approval distinct from the assessment.
98
102
  - `WAIT(reference, next-check)` requires an existing durable operation reference and
99
103
  exact reconciliation path. Missing provision is `BLOCKED(provision, owner)`.
100
104
  Uncertain effects are reconciled through the original operation and never replayed
101
105
  blindly.
102
106
  - Release preparation binds the exact accepted source set, package versions, and
103
107
  artifact digests. Later merges cannot enter an accepted cut silently. Publication
104
- remains a separate-authority placeholder.
108
+ invokes the existing project-bound workflow through its separate authorized executor;
109
+ absent executable binding remains BLOCKED with its owner.
105
110
  - Closure preserves evidence and work, positively proves no surviving writers, keeps
106
111
  producer references and delivery tags discoverable, and closes only accepted scope.
107
112
  Host-owned root effects remain referenced external operations.
@@ -165,7 +170,7 @@ authorized overseer step.
165
170
 
166
171
  Repeat the complete source inventory after edits:
167
172
 
168
- 1. Run `ace-nav explain` and `ace-nav resolve` for every selected `wfi://` and
173
+ 1. Run `ace-nav resolve --why` and `ace-nav resolve` for every selected `wfi://` and
169
174
  `guide://` URI.
170
175
  2. Load every selected workflow with `ace-bundle` and verify it came from the intended
171
176
  owner.
@@ -0,0 +1,115 @@
1
+ ---
2
+ name: maintain-continuation
3
+ description: Bootstrap and resume native coordinator duties without duplicating execution.
4
+ doc-type: workflow
5
+ title: Maintain Coordinator Continuation
6
+ purpose: Own progress audits and cleanup through the existing in-process wake extension.
7
+ ace-docs:
8
+ last-updated: '2026-10-16'
9
+ last-checked: '2026-10-16'
10
+ ---
11
+ # Maintain Coordinator Continuation
12
+
13
+ ## Goal
14
+
15
+ Keep authorized project work advancing through native wakes and canonical Assign evidence across coordinator restarts.
16
+
17
+ ## Prerequisites
18
+
19
+ Use the installed Pi ace-wake extension and the project's reviewed coordinator
20
+ role. The domain launcher owns process startup and its exact session path; ACE
21
+ owns the duty definitions below. A wake adds no execution or cleanup authority.
22
+ The selected runtime must load the reviewed package and effective project guide.
23
+
24
+ ## Project Context Loading
25
+
26
+ Load the current role, effective `guide://project-delivery`, reviewed objectives,
27
+ and existing Assign, HITL and native runtime status. Resolve assets from the
28
+ selected installed bundle; source files or remembered versions do not prove
29
+ installation. Keep the objective queue's goal, next action, blocker and references
30
+ separate from Assign's execution ownership.
31
+
32
+ ## High-Level Execution Plan
33
+
34
+ - Inspect the selected session and installed extension.
35
+ - Bootstrap duties only in a deliberately new coordinator session.
36
+ - Resume the exact existing session and verify its persisted subscriptions.
37
+ - Reconcile outcomes on each wake without repeating uncertain execution.
38
+
39
+ ## Process Steps
40
+
41
+ ### 1. Establish the native duties
42
+
43
+ For a deliberately NEW coordinator session, supply these two complete messages
44
+ to Pi's native command dispatcher before the role prompt. A supported launcher
45
+ may pass each as a separate positional initial message. They are Pi commands,
46
+ not shell commands or messages sent through the inbox/sendUserMessage API:
47
+
48
+ ```text
49
+ /loop add progress-audit --interval 600 --message Run one bounded progress audit under wfi://overseer/maintain-continuation. Reconcile current project objectives with canonical Assign attempts, results and HITL decisions; continue the next authorized action using original references. Keep unknown outcomes open and do not repeat an uncertain effect.
50
+ /loop add lifecycle-cleanup --interval 3600 --message Run one bounded cleanup audit under wfi://overseer/maintain-continuation. Reconcile owned panes and worktrees with accepted Assign results and preserved work; use the existing cleanup owner only when its preservation and no-writer gates pass. Retain active or uncertain work.
51
+ ```
52
+
53
+ Run one harmless model turn to persist the session. Verify the real session file
54
+ contains the extension's custom entries and `/loop list` reports one copy of each
55
+ duty with intervals 600 and 3600. A started process, successful prompt send or
56
+ in-memory definition alone is insufficient. Never synthesize session entries.
57
+
58
+ ### 2. Resume without re-registering
59
+
60
+ Before stopping an idle coordinator, verify its current session ID and exact
61
+ persisted session file through the native runtime. Use the launcher's supported
62
+ exact-session resume (`--session` with that verified path in Pi). Do not use a
63
+ latest-session selector or create a new session with the old ID.
64
+
65
+ On resume, let ace-wake restore its existing session entries once. Do not replay
66
+ `/loop add`, reconstruct definitions from these defaults, or recreate deliberately
67
+ removed duties. Report the restored effective subscriptions, including deliberate
68
+ removals. No missed-tick replay, second timer service or alternate scheduler.
69
+
70
+ ### 3. Audit progress every ten minutes
71
+
72
+ Inspect each selected project's objectives, canonical attempt state, native
73
+ liveness, pending review/integration and delivered HITL outcomes. Observe actual
74
+ process start and accepted results separately from dispatch acknowledgment.
75
+ Reuse the original assignment, attempt, request and mutation after a lost reply;
76
+ query/reconcile before any retry. An uncertain attempt retains its slot.
77
+
78
+ Update only the objective's next action, blocker and evidence references. Advance
79
+ one serial integration candidate after the previous canonical result; do not
80
+ rebase the entire queue. A blocked project must not prevent an independently
81
+ authorized project from progressing. Report meaningful changes or required human
82
+ action through the existing authorized project route; unchanged state stays quiet.
83
+
84
+ ### 4. Audit cleanup every hour
85
+
86
+ Reconcile exact pane/session/assignment/attempt identities. Close an owned pane
87
+ only after its result is accepted and work is durably preserved; close its tab
88
+ when that was its last pane. Worktree removal separately requires the existing
89
+ preservation and no-writer checks, including commits and valuable untracked files.
90
+ Use the existing cleanup owner's preview and accepted operation. Do not infer
91
+ permission from apparent idleness, a disappeared process or a closed pane.
92
+
93
+ ### 5. Maintain project watches
94
+
95
+ When continuation depends on a known local queue or result path, register a named
96
+ `/watch add NAME --path PATH --message TEXT` through the same native dispatcher.
97
+ Use the exact selected project's path and reconcile actual canonical state when
98
+ woken. Watches are hints, not execution receipts. Persist and resume them through
99
+ the same session mechanism; do not create an external poller to replace them.
100
+
101
+ ## Success Criteria
102
+
103
+ - The installed native session persists and restores each effective duty once.
104
+ - A real wake is consumed by the original session and produces an attributable audit.
105
+ - Repeated wakes and lost replies do not launch a second execution.
106
+ - Active or uncertain work remains preserved; cleanup uses its existing owner.
107
+ - Independent project progress and user conversation remain responsive.
108
+
109
+ ## Error Handling
110
+
111
+ Missing extension, unresolved effective guide, unavailable canonical state or a
112
+ mismatched session is an explicit blocker. Preserve the original references and
113
+ session file; do not manufacture subscriptions, silently change harness/model or
114
+ claim that a dead process will wake itself. Use the existing domain lifecycle
115
+ owner for a controlled restart and verify the resulting native session.
@@ -29,6 +29,11 @@ state, applicable scoped service grants, and existing HITL proposal history.
29
29
  Use `ace-task show TASK` and the installed public status/history interfaces for
30
30
  the actual selected project. Do not treat remembered status as current evidence.
31
31
 
32
+ For native progress and cleanup duties, follow
33
+ `wfi://overseer/maintain-continuation`: bootstrap 600-second progress and
34
+ 3600-second cleanup loops in a new session, then resume its exact persisted
35
+ session without re-adding definitions. Verify real wake consumption and results.
36
+
32
37
  ## High-Level Execution Plan
33
38
 
34
39
  - [ ] Reconcile current scope, existing executions and proposals.
@@ -75,9 +80,11 @@ the actual selected project. Do not treat remembered status as current evidence.
75
80
 
76
81
  ## Shared Decision and Responsiveness Contract
77
82
 
78
- Confirmed Hermes delivery starts the sixteen-hour proposal window. Only the
79
- existing HITL owner's healthy, drained reconciliation and resolved decision admit
80
- silent approval. Preserve approve/veto/clarify and revised/superseded history.
83
+ Confirmed Hermes delivery starts the sixteen-hour proposal window only for a
84
+ project/operation class delegated before proposal creation. The existing HITL
85
+ owner must recheck that grant during healthy, drained reconciliation; revocation
86
+ or a missing prior delegation prevents silent approval. Elapsed time alone never
87
+ authorizes a decision. Preserve approve/veto/clarify and revised/superseded history.
81
88
  A stalled resolver is deferred visibly; keep status and conversation usable and
82
89
  coalesce wakes through the existing bounded tick owner. Never wait for long
83
90
  implementation or review in the conversation handler. Selecting a role adds no
@@ -29,6 +29,11 @@ state, applicable scoped service grants, and existing HITL proposal history.
29
29
  Use `ace-task show TASK` and the installed public status/history interfaces for
30
30
  the actual selected project. Do not treat remembered status as current evidence.
31
31
 
32
+ For native progress and cleanup duties, follow
33
+ `wfi://overseer/maintain-continuation`: bootstrap 600-second progress and
34
+ 3600-second cleanup loops in a new session, then resume its exact persisted
35
+ session without re-adding definitions. Verify real wake consumption and results.
36
+
32
37
  ## High-Level Execution Plan
33
38
 
34
39
  - [ ] Reconcile current scope, existing executions and proposals.
@@ -98,7 +103,7 @@ integration MUST NOT merge and MUST NOT silently rewrite: it returns an
98
103
  actionable typed `needs-rebase` outcome to the queue owner. The queue owner
99
104
  then delegates `wfi://git/rebase` (as-git-rebase, including CHANGELOG
100
105
  preservation) in the candidate's ISOLATED worktree, obtains new exact-head
101
- checks and an independent review of the resulting exact head, updates the PR,
106
+ checks and a recorded assessment of the head change, updates the PR,
102
107
  verifies remote candidate identity and resubmits. A common old base does NOT
103
108
  make sibling heads sequentially fast-forwardable.
104
109
 
@@ -120,10 +125,10 @@ serial merge. The accepted receipt for one candidate causes preparation of
120
125
  ONLY the next selected candidate — never a mass rebase of the remaining
121
126
  queue. Each candidate, on its turn, runs the full cycle: resolve fresh
122
127
  target main; delegate `wfi://git/rebase` in that candidate's isolated
123
- worktree IF the target moved; run the applicable checks; obtain an
124
- INDEPENDENT EXPLICIT review of the resulting exact head (patch identity may
125
- support a short delta review but never substitutes the explicit independent
126
- head approval); verify the remote PR head/base; issue ONE scoped integrator
128
+ worktree IF the target moved; run the applicable checks; retain the initial independent review and record an assessment of the new head;
129
+ carry acceptance only with executed evidence of an identical rebase; obtain an
130
+ independent delta review for material or uncertain changes, including security
131
+ changes; verify the remote PR head/base; issue ONE scoped integrator
127
132
  request; wait/reconcile the actual integration receipt; refresh main; then
128
133
  select and prepare ONLY the next candidate. Queued later PRs keep their
129
134
  existing branches and heads untouched until their turn, and prior batch work
@@ -147,13 +152,15 @@ never blind-closes.
147
152
 
148
153
  Hard prohibitions: never push directly to main; never switch the canonical
149
154
  checkout to a topic branch; never reuse a stale review as approval for a
150
- different or moved head.
155
+ different or moved head without the recorded assessment and required evidence.
151
156
 
152
157
  ## Shared Decision and Responsiveness Contract
153
158
 
154
- Confirmed Hermes delivery starts the sixteen-hour proposal window. Only the
155
- existing HITL owner's healthy, drained reconciliation and resolved decision admit
156
- silent approval. Preserve approve/veto/clarify and revised/superseded history.
159
+ Confirmed Hermes delivery starts the sixteen-hour proposal window only for a
160
+ project/operation class delegated before proposal creation. The existing HITL
161
+ owner must recheck that grant during healthy, drained reconciliation; revocation
162
+ or a missing prior delegation prevents silent approval. Elapsed time alone never
163
+ authorizes a decision. Preserve approve/veto/clarify and revised/superseded history.
157
164
  A stalled resolver is deferred visibly; keep status and conversation usable and
158
165
  coalesce wakes through the existing bounded tick owner. Never wait for long
159
166
  implementation or review in the conversation handler. Selecting a role adds no
@@ -69,9 +69,11 @@ the actual selected project. Do not treat remembered status as current evidence.
69
69
 
70
70
  ## Shared Decision and Responsiveness Contract
71
71
 
72
- Confirmed Hermes delivery starts the sixteen-hour proposal window. Only the
73
- existing HITL owner's healthy, drained reconciliation and resolved decision admit
74
- silent approval. Preserve approve/veto/clarify and revised/superseded history.
72
+ Confirmed Hermes delivery starts the sixteen-hour proposal window only for a
73
+ project/operation class delegated before proposal creation. The existing HITL
74
+ owner must recheck that grant during healthy, drained reconciliation; revocation
75
+ or a missing prior delegation prevents silent approval. Elapsed time alone never
76
+ authorizes a decision. Preserve approve/veto/clarify and revised/superseded history.
75
77
  A stalled resolver is deferred visibly; keep status and conversation usable and
76
78
  coalesce wakes through the existing bounded tick owner. Never wait for long
77
79
  implementation or review in the conversation handler. Selecting a role adds no
File without changes
File without changes
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../../organisms/ordinary_work_on"
4
+
5
+ module Ace
6
+ module Overseer
7
+ module CLI
8
+ module Commands
9
+ class Ordinary < Ace::Support::Cli::Command
10
+ desc "Prepare, launch or resume one ordinary execution through installed Assign"
11
+ option :operation, required: true, desc: "prepare, launch, status, resume (status/resume never dispatch)"
12
+ option :project, required: true, desc: "Installed ordinary project ID"
13
+ option :task, desc: "Reviewed leaf task for preparation"
14
+ option :checkout, desc: "Explicit project checkout validated against installed common directory"
15
+ option :output, desc: "New private retained input directory for preparation"
16
+ option :provider, desc: "Explicit interactive provider/model/thinking selection"
17
+ option :context, desc: "Original context.json for launch/status/resume"
18
+
19
+ def call(operation:, project:, **options)
20
+ entry = Organisms::OrdinaryWorkOn.new
21
+ result = case operation
22
+ when "prepare"
23
+ entry.prepare(project: project, task: options.fetch(:task), checkout: options.fetch(:checkout),
24
+ output: options.fetch(:output), provider: options.fetch(:provider))
25
+ when "launch" then entry.launch(project: project, context: options.fetch(:context))
26
+ when "status", "resume" then entry.resume(project: project, context: options.fetch(:context))
27
+ else raise ArgumentError, "unknown ordinary operation"
28
+ end
29
+ puts JSON.generate(result)
30
+ rescue ArgumentError, KeyError, SystemCallError, Ace::Overseer::Error, Ace::Assign::Error, Ace::Lab::Error, Ace::Runtime::Error, Ace::LLM::Error => error
31
+ raise Ace::Support::Cli::Error, "ordinary handoff incomplete: #{error.message}; retain its inputs and inspect the original context"
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -10,6 +10,7 @@ require_relative "cli/commands/agents"
10
10
  require_relative "cli/commands/prompt"
11
11
  require_relative "cli/commands/review"
12
12
  require_relative "cli/commands/stop"
13
+ require_relative "cli/commands/ordinary"
13
14
 
14
15
  module Ace
15
16
  module Overseer
@@ -20,6 +21,7 @@ module Ace
20
21
 
21
22
  REGISTERED_COMMANDS = [
22
23
  ["work-on", "Start local task work or one retained protected launch"],
24
+ ["ordinary", "Prepare, launch, inspect or resume one installed ordinary execution"],
23
25
  ["status", "Show status of task worktrees"],
24
26
  ["prune", "Remove stale task worktrees"],
25
27
  ["projects", "List visible public projects"],
@@ -36,6 +38,7 @@ module Ace
36
38
  ].freeze
37
39
 
38
40
  register "work-on", Commands::WorkOn
41
+ register "ordinary", Commands::Ordinary
39
42
  register "status", Commands::Status
40
43
  register "prune", Commands::Prune
41
44
  register "projects", Commands::Projects
File without changes
File without changes
File without changes
@@ -0,0 +1,186 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "shellwords"
4
+ require "ace/lab/organisms/ordinary_assignment_client"
5
+ require "ace/lab/molecules/ordinary_worktree_read"
6
+ require "ace/assign/organisms/ordinary_driver"
7
+ require "ace/assign/molecules/runtime_control_surface_runner"
8
+ require "ace/llm"
9
+
10
+ module Ace
11
+ module Overseer
12
+ module Organisms
13
+ # Ordinary entry: existing worktree/native launch mechanisms, immutable
14
+ # request inputs, and canonical Assign observations. No local execution.
15
+ class OrdinaryWorkOn
16
+ Files = Ace::Assign::Authority::RetainedInput
17
+
18
+ def initialize(config: nil, runtime: nil, provisioner: nil, windows: nil, builder: nil, client: nil, prepare: nil, observer: nil)
19
+ @config, @runtime = config, runtime
20
+ @provisioner = provisioner
21
+ @windows = windows
22
+ @builder = builder
23
+ @client = client
24
+ @prepare = prepare || Ace::Lab::Organisms::OrdinaryAssignmentClient.method(:prepare)
25
+ @observer = observer
26
+ end
27
+
28
+ def prepare(project:, task:, checkout:, output:, provider:)
29
+ config = selected(project)
30
+ caller = supervisor!(config)
31
+ checkout = File.realpath(checkout)
32
+ # The native coordinator can live in a different project. Explicit
33
+ # preparation cwd must resolve to this installed common directory.
34
+ source_reader = @observer || Ace::Lab::Molecules::OrdinaryWorktreeRead.new(root: checkout,
35
+ common_dir: config.worktrees.fetch("common_dir"), deadline: Process.clock_gettime(Process::CLOCK_MONOTONIC) + 30)
36
+ source_reader.observe(checkout)
37
+ directory = Files.create_output(output)
38
+ worktree = in_worktree(checkout) do
39
+ provisioner = @provisioner || Molecules::WorktreeProvisioner.new(
40
+ manager: Ace::Git::Worktree::Organisms::WorktreeManager.new(project_root: checkout))
41
+ provisioner.provision(task).fetch(:worktree_path)
42
+ end
43
+ cwd = validate_worktree!(config, worktree)
44
+ # Resolve actual provider arguments before creating any pane/agent.
45
+ prepared = in_worktree(cwd) do
46
+ (@builder || Ace::LLM::Molecules::InteractiveCommandBuilder.new).build(
47
+ provider_model: provider, prompt: "ordinary preparation", working_dir: cwd)
48
+ @prepare.call(project: project, task: task, pane: caller.fetch(:pane), output: File.join(directory, "prepared"))
49
+ end
50
+ window = (@windows || Molecules::WindowOpener.new(runtime: runtime)).open(worktree_path: cwd)
51
+ pane = runtime.prepare_pane(window: window)
52
+ context = {"version" => 1, "project_id" => project, "assignment_id" => prepared.fetch("assignment_id"),
53
+ "attempt_id" => SecureRandom.hex(16), "scope" => prepared.fetch("scope"), "pane" => pane,
54
+ "supervisor_pane" => caller.fetch(:pane), "cwd" => cwd,
55
+ "head" => observe(config, cwd).fetch("head"), "provider" => provider}
56
+ Files.write_file(directory, "context.json", JSON.generate(context) + "\n")
57
+ Files.write_file(directory, "result-hint.json", JSON.generate({"hint_only" => true}))
58
+ registration = client(project).request(input: prepared.fetch("request"))
59
+ unless registration.dig("data", "assignment_id") == prepared.fetch("assignment_id") &&
60
+ registration.dig("data", "project_id") == project
61
+ raise Error, "ordinary registration returned a different project or assignment; recover #{directory}/context.json"
62
+ end
63
+ describe(File.join(directory, "context.json"), context).merge("state" => "ready_not_dispatched", "window" => window)
64
+ end
65
+
66
+ def launch(project:, context:)
67
+ driver = driver(project, context)
68
+ selected_context = driver.context
69
+ config = selected(project)
70
+ caller = supervisor!(config)
71
+ supervisor = driver.supervisor
72
+ unless runtime.process_binding(pane: caller.fetch(:pane), caller_pid: Process.pid) == supervisor.fetch("binding")
73
+ raise Error, "ordinary launch belongs to the canonical native supervisor; adopt explicitly after its previous generation ends"
74
+ end
75
+ cwd = validate_worktree!(config, selected_context.fetch("cwd"))
76
+ directory = File.dirname(driver.path)
77
+ # Canonical supervisor lookup also proves registration. Recovery does
78
+ # not register again or reconstruct work from a local assignment cache.
79
+ observed = driver.status
80
+ return describe(driver.path, selected_context).merge("canonical" => observed) unless observed.fetch("state") == "not_started"
81
+ unless observe(config, cwd).fetch("head") == selected_context.fetch("head")
82
+ raise Error, "ordinary launch checkout moved; preserve original context and reconcile before dispatch"
83
+ end
84
+ invocation = in_worktree(cwd) do
85
+ (@builder || Ace::LLM::Molecules::InteractiveCommandBuilder.new).build(provider_model: selected_context.fetch("provider"),
86
+ prompt: "/as-assign-drive --ordinary #{driver.path.shellescape}", working_dir: cwd,
87
+ subprocess_env: {"ACE_ASSIGN_ORDINARY_CONTEXT" => driver.path,
88
+ "ACE_ASSIGN_ORDINARY_PROJECT" => project, "ACE_RUNTIME" => "herdr"})
89
+ end
90
+ # Create before native send. A lost send/reply cannot cause another
91
+ # invocation. Resume only observes; it never deletes this intent.
92
+ intent = {"pane" => selected_context.fetch("pane"), "assignment_id" => selected_context.fetch("assignment_id"),
93
+ "attempt_id" => selected_context.fetch("attempt_id"), "provider" => invocation.fetch(:provider),
94
+ "model" => invocation.fetch(:model), "thinking_level" => invocation[:thinking_level],
95
+ "command_sha256" => Digest::SHA256.hexdigest(invocation.fetch(:command).to_json)}
96
+ begin
97
+ Files.write_file(directory, "dispatch.json", JSON.generate(intent) + "\n")
98
+ rescue Errno::EEXIST
99
+ return describe(driver.path, selected_context).merge("state" => "dispatch_uncertain", "canonical" => observed,
100
+ "remediation" => "Inspect the original pane and canonical status; never launch a replacement from this context")
101
+ end
102
+ runner = Ace::Assign::Molecules::RuntimeControlSurfaceRunner.new(runtime: "herdr", adapter: runtime)
103
+ runner.run_invocation_in_pane(pane_target: selected_context.fetch("pane"), command: invocation.fetch(:command),
104
+ env: invocation[:env], working_dir: invocation.fetch(:working_dir), visible_handoff: invocation[:prompt])
105
+ describe(driver.path, selected_context).merge("state" => "accepted_not_started", "canonical" => driver.status)
106
+ end
107
+
108
+ # Restart/recovery is an observation of original IDs, never redispatch.
109
+ def resume(project:, context:)
110
+ driver = driver(project, context)
111
+ describe(driver.path, driver.context).merge("canonical" => driver.status,
112
+ "supervisor" => driver.supervisor,
113
+ "dispatch_intent" => File.file?(File.join(File.dirname(driver.path), "dispatch.json")))
114
+ end
115
+
116
+ private
117
+
118
+ def selected(project)
119
+ config = @config || Ace::Lab::Molecules::OrdinaryOwnerConfig.load(project: project)
120
+ raise Error, "ordinary project selection differs" unless config.project == project
121
+ config.verify_owner!
122
+ config
123
+ end
124
+
125
+ def client(project)
126
+ @client || Ace::Lab::Organisms::OrdinaryAssignmentClient.new(project: project)
127
+ end
128
+
129
+ def driver(project, context)
130
+ Ace::Assign::Organisms::OrdinaryDriver.new(path: context, project: project, transport: client(project))
131
+ end
132
+
133
+ def runtime
134
+ @runtime ||= Ace::Herdr::Organisms::RuntimeAdapter.new
135
+ end
136
+
137
+ def supervisor!(config)
138
+ participant = config.selected_principal!(Process.uid)
139
+ caller = runtime.context
140
+ unless caller[:in_runtime] && caller[:session] == participant.fetch("workspace") &&
141
+ participant.fetch("supervisor_panes").include?(caller[:pane])
142
+ raise Error, "ordinary preparation and launch require the selected native supervisor"
143
+ end
144
+ caller
145
+ end
146
+
147
+ def validate_worktree!(config, path)
148
+ actual = File.realpath(path)
149
+ root = File.realpath(config.worktrees.fetch("root"))
150
+ raise Error, "ordinary worktree is outside installed project selection" unless actual.start_with?(root + "/")
151
+ actual
152
+ end
153
+
154
+ def observe(config, cwd)
155
+ reader = @observer || Ace::Lab::Molecules::OrdinaryWorktreeRead.new(root: config.worktrees.fetch("root"),
156
+ common_dir: config.worktrees.fetch("common_dir"), deadline: Process.clock_gettime(Process::CLOCK_MONOTONIC) + 30)
157
+ reader.observe(cwd)
158
+ end
159
+
160
+ def in_worktree(path)
161
+ previous = ENV["PROJECT_ROOT_PATH"]
162
+ Dir.chdir(path) do
163
+ ENV["PROJECT_ROOT_PATH"] = path
164
+ Ace::Support::Fs::Molecules::ProjectRootFinder.clear_cache!
165
+ Ace::Assign.reset_config!
166
+ Ace::LLM.reset_configuration!
167
+ yield
168
+ end
169
+ ensure
170
+ ENV["PROJECT_ROOT_PATH"] = previous
171
+ Ace::Support::Fs::Molecules::ProjectRootFinder.clear_cache!
172
+ Ace::Assign.reset_config!
173
+ Ace::LLM.reset_configuration!
174
+ end
175
+
176
+ def describe(path, context)
177
+ read = "ace-lab assignment drive --project #{context.fetch('project_id').shellescape} --context #{path.shellescape} --operation status"
178
+ {"context" => path, **context.slice("project_id", "assignment_id", "attempt_id", "scope", "pane", "supervisor_pane", "cwd", "provider"),
179
+ "watch_command" => "/watch add ordinary-#{context.fetch('attempt_id')} --path #{File.join(File.dirname(path), 'result-hint.json').to_json} " \
180
+ "--message #{("Ordinary result hint only. Run #{read}; adopt only its exact canonical submitted result. Preserve original IDs on uncertainty.").to_json}",
181
+ "status_command" => read}
182
+ end
183
+ end
184
+ end
185
+ end
186
+ end
File without changes
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Ace
4
4
  module Overseer
5
- VERSION = "0.21.1"
5
+ VERSION = "0.23.0"
6
6
  end
7
7
  end
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.21.1
4
+ version: 0.23.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michal Czyz
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2026-10-14 00:00:00.000000000 Z
10
+ date: 2026-10-16 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: ace-support-cli
@@ -71,14 +71,14 @@ dependencies:
71
71
  requirements:
72
72
  - - "~>"
73
73
  - !ruby/object:Gem::Version
74
- version: '0.67'
74
+ version: '0.70'
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.67'
81
+ version: '0.70'
82
82
  - !ruby/object:Gem::Dependency
83
83
  name: ace-git
84
84
  requirement: !ruby/object:Gem::Requirement
@@ -113,14 +113,14 @@ dependencies:
113
113
  requirements:
114
114
  - - "~>"
115
115
  - !ruby/object:Gem::Version
116
- version: '0.37'
116
+ version: '0.40'
117
117
  type: :runtime
118
118
  prerelease: false
119
119
  version_requirements: !ruby/object:Gem::Requirement
120
120
  requirements:
121
121
  - - "~>"
122
122
  - !ruby/object:Gem::Version
123
- version: '0.37'
123
+ version: '0.40'
124
124
  - !ruby/object:Gem::Dependency
125
125
  name: ace-runtime
126
126
  requirement: !ruby/object:Gem::Requirement
@@ -155,42 +155,42 @@ dependencies:
155
155
  requirements:
156
156
  - - "~>"
157
157
  - !ruby/object:Gem::Version
158
- version: 0.5.1
158
+ version: '0.6'
159
159
  type: :runtime
160
160
  prerelease: false
161
161
  version_requirements: !ruby/object:Gem::Requirement
162
162
  requirements:
163
163
  - - "~>"
164
164
  - !ruby/object:Gem::Version
165
- version: 0.5.1
165
+ version: '0.6'
166
166
  - !ruby/object:Gem::Dependency
167
167
  name: ace-lab
168
168
  requirement: !ruby/object:Gem::Requirement
169
169
  requirements:
170
170
  - - "~>"
171
171
  - !ruby/object:Gem::Version
172
- version: '0.6'
172
+ version: '0.8'
173
173
  type: :runtime
174
174
  prerelease: false
175
175
  version_requirements: !ruby/object:Gem::Requirement
176
176
  requirements:
177
177
  - - "~>"
178
178
  - !ruby/object:Gem::Version
179
- version: '0.6'
179
+ version: '0.8'
180
180
  - !ruby/object:Gem::Dependency
181
181
  name: ace-review
182
182
  requirement: !ruby/object:Gem::Requirement
183
183
  requirements:
184
184
  - - "~>"
185
185
  - !ruby/object:Gem::Version
186
- version: 0.60.1
186
+ version: 0.61.0
187
187
  type: :runtime
188
188
  prerelease: false
189
189
  version_requirements: !ruby/object:Gem::Requirement
190
190
  requirements:
191
191
  - - "~>"
192
192
  - !ruby/object:Gem::Version
193
- version: 0.60.1
193
+ version: 0.61.0
194
194
  - !ruby/object:Gem::Dependency
195
195
  name: ace-support-test-helpers
196
196
  requirement: !ruby/object:Gem::Requirement
@@ -275,6 +275,7 @@ files:
275
275
  - handbook/skills/as-overseer/SKILL.md
276
276
  - handbook/workflow-instructions/overseer.wf.md
277
277
  - handbook/workflow-instructions/overseer/configure-project.wf.md
278
+ - handbook/workflow-instructions/overseer/maintain-continuation.wf.md
278
279
  - handbook/workflow-instructions/roles/lab-coordinator.wf.md
279
280
  - handbook/workflow-instructions/roles/project-overseer.wf.md
280
281
  - handbook/workflow-instructions/roles/second-commander.wf.md
@@ -285,6 +286,7 @@ files:
285
286
  - lib/ace/overseer/atoms/status_formatter.rb
286
287
  - lib/ace/overseer/cli.rb
287
288
  - lib/ace/overseer/cli/commands/agents.rb
289
+ - lib/ace/overseer/cli/commands/ordinary.rb
288
290
  - lib/ace/overseer/cli/commands/projects.rb
289
291
  - lib/ace/overseer/cli/commands/prompt.rb
290
292
  - lib/ace/overseer/cli/commands/prune.rb
@@ -309,6 +311,7 @@ files:
309
311
  - lib/ace/overseer/molecules/worktree_context_collector.rb
310
312
  - lib/ace/overseer/molecules/worktree_provisioner.rb
311
313
  - lib/ace/overseer/organisms/launch_recovery.rb
314
+ - lib/ace/overseer/organisms/ordinary_work_on.rb
312
315
  - lib/ace/overseer/organisms/protected_prune.rb
313
316
  - lib/ace/overseer/organisms/protected_review.rb
314
317
  - lib/ace/overseer/organisms/protected_status.rb