ace-overseer 0.27.0 → 0.28.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5204d8b317b630a73e16ddc196fc90c3d6efa1e0f39a62406e1b6f7bd6de4c2e
4
- data.tar.gz: 5293bfde27b37ca690442f2ffcc60446913ec54052b2426b47d82c55d48c1614
3
+ metadata.gz: 4d96c79ae10f470e6358022f081234f5080eba56cd58353471a33aa6f187e0c5
4
+ data.tar.gz: 5e4eadc41222d3448b57f938ad5c2716b1941ddfe7b800479d69a6a3f72f3cb9
5
5
  SHA512:
6
- metadata.gz: 96747e1a1d70f884fb302110f0f12197b81a4b6a7701ce0ef0aeb000581daaae7bc6ccb7660f15fdf1ef067e6c879c0e3c86e774881b99ffdd351ec82204a740
7
- data.tar.gz: 61e8da9b71790c8f7f5252e61652d4d7af4dd881d4bb8e716504c84ee60cfc1af3e784f0c5d8172d096e471d353d010e674984a9cee99d1a0b63e1e40d0c9eac
6
+ metadata.gz: f9fdda6024283fd16b8be35da318b7e4eb6a85574ef623cc1395c4c7af0d77fc1971a541bb2a28abe3a6ce7a6d52f1c04df442c69eaff53e09f7d3974b6b89e3
7
+ data.tar.gz: 4fe70abfe425a0c399763c790125f391bbca8099f5a96e4a24677047148fc4b7e1c578ae976853195a28f1e5306500e259de498a491601e241e1c82e1b514c91
data/CHANGELOG.md CHANGED
@@ -5,6 +5,53 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [Unreleased]
9
+
10
+ ## [0.28.1] - 2026-10-31
11
+
12
+ ### Fixed
13
+
14
+ - Transfer terminal runtime setup through a private script and require its
15
+ acknowledgement before launch, preventing canonical-input PATH truncation.
16
+
17
+ - Bind unassigned readiness only to explicit planner allocations; reject missing
18
+ report identities and conflicting task/role references. Persist bootstrap
19
+ assignment and receipt identities in task metadata, using resolved task paths.
20
+ Check real completed assignment and role ownership before accepting success;
21
+ leave confirm-start continuation to the coordinator without worker dispatch.
22
+
23
+ - Preserve concrete child startup failures reported before project scope is
24
+ established, while continuing to reject unscoped or wrong-scope success.
25
+
26
+ - Delegate bootstrap diagnosis and reproduction to workers as well as repair;
27
+ a known symptom is enough to commission work. Reconcile project startup only
28
+ after accepted worker completion and independent verification.
29
+
30
+ ## [0.28.0] - 2026-10-31
31
+
32
+ ### Fixed
33
+
34
+ - Delegate lab bootstrap to workers and independent verification; distinguish
35
+ preparation/printed briefs from running agents and confirmed first turns.
36
+ - Preserve installed operational runtime across project starts.
37
+ - Normalize local observation identities for the eyes wire contract.
38
+
39
+ ## [0.28.0.pre.3] - 2026-10-31
40
+
41
+ ### Fixed
42
+
43
+ - Child project bundles no longer inherit a forced Lab `ACE_TOOLCHAIN` mode;
44
+ project-selected path/source dependencies and explicit child policies remain
45
+ authoritative. The Lab role may perform routine project startup setup without
46
+ taking over project deliverables.
47
+ - `ace-overseer start` bootstraps missing start settings and becomes the Lab
48
+ coordinator in the current terminal without Herdr preflight. Explicit
49
+ `start --reconcile` manages project children after agent initialization. The coordinator can configure itself using the packaged guide.
50
+ - Lab and project workspaces use `overseer` and topology ids such as `ace`,
51
+ independently of session ownership labels. Project startup executes each
52
+ project's own Gemfile/lock and binstub in a separate process; project panes
53
+ use their own bundle instead of inheriting the Lab's gem runtime.
54
+
8
55
  ## [0.27.0] - 2026-10-30
9
56
 
10
57
  ### Fixed (review rounds 3/3b)
data/docs/usage.md CHANGED
@@ -32,14 +32,21 @@ authority execution model. tmux and Herdr are transports, never state owners.
32
32
 
33
33
  ## `ace-overseer start`
34
34
 
35
- Start or reuse the PROJECT overseer session from the directory's own
36
- configuration (task 8xs.t.pu0.1). The start contract is explicit — nothing is
37
- guessed and no interim default model applies:
35
+ Run `ace-overseer start` at a shell in the Lab's existing Herdr `overseer`
36
+ space. The command becomes the Lab's Pi agent directly in that same terminal
37
+ and cwd, without any Herdr environment, agent, owner or layout preflight. The agent receives the packaged Lab guide
38
+ and a first-turn prompt to delegate configuration of commissioned projects
39
+ using installed CLI, skills and normal configuration editing.
40
+
41
+ No local start YAML is required for first run. The packaged bootstrap profile
42
+ is `pi`, `zai/glm-5.3-flash`, thinking `high`, in Lab scope. An explicit start
43
+ section overrides bootstrap and is validated without fallback. For an
44
+ explicit project start use:
38
45
 
39
46
  ```yaml
40
47
  # .ace/overseer/config.yml (project tier of the cascade)
41
48
  start:
42
- scope: project # project | lab (lab: not implemented yet)
49
+ scope: project # project | lab
43
50
  profile: overseer-default # reference into the profiles map below
44
51
  instructions: wfi://overseer/start # handbook source (or absolute file path)
45
52
  profiles:
@@ -53,6 +60,8 @@ profiles:
53
60
  |--------|---------|
54
61
  | `--dry-run` | Show the start plan; no session, no sync, no model call |
55
62
  | `--format` | `table` (default) or `json` |
63
+ | `--reconcile` | Explicitly reconcile project children after the agent configures the Lab; never restart the coordinator |
64
+ | `--scope` | Explicit `lab` or `project` role; an unconfigured bare start bootstraps the Lab |
56
65
 
57
66
  Behavior:
58
67
 
@@ -86,15 +95,37 @@ Behavior:
86
95
  - The report carries `status` (`started|reused|blocked|dry_run`), `scope`,
87
96
  `root`, `label`, `workspace`, `pane`, `agent`, `profile`, `instructions`
88
97
  (`source` + resolved `path`) and a `message`. Exit 0 only for a ready
89
- start/reuse (dry-run included); a blocked start is a CLI error naming the
90
- missing configuration.
98
+ start/reuse (dry-run included); a blocked start is a CLI error naming the concrete invalid configuration
99
+ or unavailable capability.
91
100
  - The started overseer coordinates and delegates (guide:
92
101
  `wfi://overseer/start`); it never substitutes for a missing coworker.
93
102
 
103
+ ### Project-local bundles
104
+
105
+ In auto mode each project owns its Gemfile/lock and binstubs. Child starts
106
+ clear parent Bundler/Ruby injection and select the project's bundle.
107
+
108
+ Explicit `ACE_TOOLCHAIN=installed` is preserved instead: the installed
109
+ Toolchain launcher and gem closure start the child without reading its
110
+ Gemfile or executing its binstub. Missing installed dependencies fail visibly;
111
+ there is no fallback to checkout code. Terminal backend selection does not
112
+ change toolchain mode.
113
+
114
+ The lab overseer delegates bundle/configuration preparation to a lab worker;
115
+ it never edits the project's binstub or installs gems itself. Follow
116
+ `wfi://overseer/bootstrap-delegation` for the task, worker, independent
117
+ verification and observed completion cycle. `ace-coworker start` prints a
118
+ brief; a separate Herdr agent launch and first prompt are required.
119
+
94
120
  ### Lab scope (8xs.t.pu0.a)
95
121
 
96
122
  `scope: lab` in the LAB coordination directory's own `.ace/overseer/config.yml`
97
- starts the whole lab from one external entry point:
123
+ selects the Lab role. Bare `start` launches the foreground harness;
124
+ `start --reconcile` is the explicit tool the agent uses after configuring its
125
+ projects. Reconciliation manages project children without restarting or probing
126
+ the Lab coordinator. The older full orchestration operation remains available
127
+ explicitly through `start --scope lab`:
128
+
98
129
 
99
130
  - The project list and CANONICAL locations come from the existing ace-lab
100
131
  topology (`topology.projects` id/path, read internally — the public
@@ -105,17 +136,14 @@ starts the whole lab from one external entry point:
105
136
  per-project (a nested lab start never recurses). An unreadable topology
106
137
  (missing or unparseable `.ace/lab/config.yml`) is a blocked start with
107
138
  the concrete cause.
108
- - The lab creates/reuses its own herdr space (`lab-overseer` — namespaced
109
- so it can never collide with a session/space title derived from a project
110
- directory name, e.g. a project rooted at a directory named `lab` owns
111
- `overseer-lab`) and boots or
139
+ - The lab creates/reuses its own herdr space (`overseer`, reserved for the Lab) and boots or
112
140
  reuses the lab's OWN overseer session there (label `overseer-<lab-root>`,
113
141
  cwd at the lab root, the lab guide as standing instructions, first-turn
114
142
  prompt included) — the lab-start instructions always reach a real agent,
115
143
  and an empty configured project list still runs the lab overseer (idle).
116
- - EACH project then starts or is found through the SAME operation as a
144
+ - EACH project then starts or is found through its own bundle and the SAME operation as a
117
145
  standalone start (its own cascade, root, and session identity) in its OWN
118
- herdr space, titled by its session label (`overseer-<project>`) and
146
+ herdr space, titled by its topology id (for example `ace`) and
119
147
  created/reused by title by the lab flow — project sessions are isolated
120
148
  from each other and from the lab overseer, never share one space, and
121
149
  never re-resolve the caller's ambient workspace (a plain terminal without
@@ -532,3 +560,15 @@ ace-overseer prune --dry-run
532
560
  ace-overseer prune --yes
533
561
  ace-overseer prune --dry-run
534
562
  ```
563
+
564
+ ### Workspace names and foreground instructions
565
+
566
+ Topology IDs reserve workspace titles for the commissioned lab projects.
567
+ Reconciliation may reuse an existing workspace with that title, but never
568
+ replaces its manual panes; project ownership is the stable overseer tab label
569
+ plus canonical cwd, not the mutable terminal title. Ambiguous ownership blocks.
570
+
571
+ Foreground bootstrap pins the two built-in start guides to their packaged
572
+ files. An explicit custom instruction source remains configurable; missing
573
+ files block before launching Pi. Project development dependencies do not select
574
+ the operational runtime when installed mode is chosen.
@@ -0,0 +1,119 @@
1
+ ---
2
+ name: overseer-bootstrap-delegation
3
+ description: Delegate project startup to lab workers and accept their observed results
4
+ allowed-tools: Bash, Read
5
+ doc-type: workflow
6
+ title: Delegated Project Bootstrap
7
+ purpose: Complete one lab-owned startup commission without the overseer doing the repair.
8
+ ---
9
+ # Delegated project bootstrap
10
+
11
+ ## Commission and ownership
12
+
13
+ The overseer reads owner state and public CLI contracts to establish scope,
14
+ existing execution and the observed symptom. Technical diagnosis, source-code
15
+ investigation, troubleshooting and reproduction commands belong to the worker.
16
+ Record the known failure and desired outcome in the commission; discovering
17
+ the root cause is part of the assigned work, never a prerequisite for dispatch.
18
+ Use existing readiness state, or a startup dry run only when that state is
19
+ otherwise unknown. Do not turn that check into a technical investigation.
20
+ Once the symptom is known, proceed to task creation/reconciliation, observation
21
+ and worker dispatch, then end the turn.
22
+
23
+ Read existing tasks and assignments first. Reuse the open commission for the
24
+ same project and goal; unknown execution state never means free capacity.
25
+ Create one lab coordination task in `_overseer`, with three direct children:
26
+ prepare, independently verify, confirm start. The latter two depend on their
27
+ predecessor. Only the lab overseer updates this private tree.
28
+
29
+ Create a separate executable lab task through `ace-task` for the bootstrap
30
+ work, linking it as the manager's `project_task`. Keep its specification in
31
+ its task folder. Include the canonical target repository path, required
32
+ configuration, observed failure, desired outcome, allowed changes, runtime
33
+ mode, acceptance checks and report recipient. Assign diagnosis and reproduction
34
+ as well as preparation to the worker. This is lab infrastructure work, not a project product task.
35
+ Workers must not edit the private coordination tree. Resolve each task folder
36
+ from `ace-task show <ref>` before writing commission, dispatch or receipt notes;
37
+ never construct a folder from a guessed or expanded title slug.
38
+
39
+ Explicit `ACE_TOOLCHAIN=installed` remains installed in every subprocess,
40
+ worker and resumed session. The project checkout is domain data. Never modify
41
+ tracked binstubs to bypass this selection. In auto mode retain the project's
42
+ own dependency model. If package code is defective, commission its repair;
43
+ do not patch installed gems. Preserve unrelated changes.
44
+
45
+ ## Arm eyes before dispatch
46
+
47
+ Use the lab's existing eyes JSON configuration. The `ace_eyes` tool accepts
48
+ `{"action":"start","configPath":"<absolute eyes JSON path>"}`.
49
+ Inspect the returned state: enabled=true, breaker=null, errors=0 and at least
50
+ one observation. Read pending revisions from their original owners, reconcile
51
+ existing commissions, and ack each exact key/revision only after acceptance.
52
+ A missing extension, invalid configuration or degraded source blocks dispatch;
53
+ report that capability gap. Do not claim that mentioning `/eyes` armed it.
54
+
55
+ ## Prepare and actually launch a worker
56
+
57
+ Use `ace-coworker prepare --task <executable-task> --roles bootstrap-worker,bootstrap-verifier
58
+ --to <configured-overseer-address> --format json`. Read its returned worktree,
59
+ assignment IDs and start-config paths; record these on the matching private
60
+ steps before launch through the task API, not only in prose:
61
+
62
+ ```bash
63
+ ace-task update <prepare-step> --set assignment=<worker-assignment> --set role=bootstrap-worker --set worktree=<returned-worktree>
64
+ ace-task update <verify-step> --set assignment=<verifier-assignment> --set role=bootstrap-verifier --set worktree=<returned-worktree>
65
+ ace-task update <confirm-step> --set role=confirm-start
66
+ ```
67
+
68
+ Read back the steps with `ace-task show` and verify exact returned identities.
69
+ A preparation readiness report is not worker completion. It does not complete
70
+ any of these three steps; never label bootstrap execution as `role=planner`.
71
+ Only a separate, explicitly commissioned planner preparation allocation may
72
+ accept an unassigned readiness report.
73
+ The task must be present in the execution worktree before any agent starts.
74
+
75
+ `ace-coworker start --config <returned-path>` validates and prints a brief;
76
+ it does NOT launch an agent. Use the configured Herdr provider/profile to
77
+ start a separate worker agent in the returned worktree, load the returned
78
+ role instructions, and send its first prompt. The prompt commissions only
79
+ that task and pinned assignment, requires the worker to read its start brief,
80
+ drive that assignment, and finish with `ace-coworker report`. These operational roles explicitly allow the commissioned canonical target
81
+ outside the lab task worktree; ordinary product worker/reviewer roles do not.
82
+ Use CLI help for
83
+ Herdr's current arguments. Record the returned pane/agent identity and verify
84
+ first-turn delivery. Never replace a missing executor with your own work.
85
+
86
+ End the overseer's turn immediately after dispatch. The eyes timer observes
87
+ assignment and HITL revisions without invoking the model on unchanged state.
88
+
89
+ ## Receive, verify, start
90
+
91
+ On wake, read the original report and current assignment. Require matching
92
+ report ID, task, assignment and role; a preparation report, process exit or
93
+ unmatched message is not success. Use `ace-overseer process-reports --dry-run`
94
+ to inspect the matching and continuation before applying it. Only accept
95
+ worker success with a completed non-empty assignment and the promised evidence.
96
+ Record the actual accepted HITL event ID and result in step metadata through
97
+ `ace-task update <step> --set processed_report=<event-id> --set report_result=<result>`
98
+ (or let `process-reports` perform that same write after its dry run is checked).
99
+ Mark done only after acceptance; errors keep the step open. Receipt notes in
100
+ the path returned by `ace-task show` supplement these fields, never replace them.
101
+ Read back the recorded identity before acknowledging the eyes revision.
102
+ Never put a preparation readiness ID on a worker, verifier or confirm-start step.
103
+
104
+ Use the existing role handoff gate to prepare the independent reviewer after
105
+ worker completion. As with the worker, a printed start command is not a live
106
+ agent: launch the reviewer separately with its own returned role/config and
107
+ confirm first-turn delivery. Do not launch a second executor while an earlier
108
+ one is active or its state is unknown. On repeated delivery, reconcile existing
109
+ assignments and agents instead of dispatching again.
110
+
111
+ Only after accepted worker completion and independent verification does the
112
+ overseer perform this commission's project-start coordination operation `ace-overseer start --reconcile`. Confirm the target's session, first
113
+ turn and active eyes from actual session evidence. A ready process alone is
114
+ not initialized observation. Close the confirmation step and managing task
115
+ only with these proofs; the worker report alone cannot close the family.
116
+
117
+ On error, keep the step open and route repair to the worker. Missing authority
118
+ or an actual Captain decision becomes a precise HITL question; end the turn
119
+ armed for its answer. Never self-repair or use sleep-poll while waiting.
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: overseer-lab-start
3
3
  description: Standing instructions for a started LAB overseer session (aggregate project readiness, escalate across projects, delegate to project overseers)
4
- allowed-tools: Bash, Read
4
+ allowed-tools: Bash, Read, Write, Edit
5
5
  doc-type: workflow
6
6
  title: Lab Overseer Start Guide
7
7
  purpose: Define the lab overseer's coordination role across projects — readiness aggregation, cross-project escalation, delegation to project overseers — without taking over any project's tasks or private state.
@@ -20,21 +20,61 @@ aggregating their status and escalations, and routing the Captain's goals to
20
20
  the right project. You never take over a project's tasks, worktrees, or
21
21
  private `_overseer` state — those belong to each project's overseer.
22
22
 
23
+ You own the OUTCOME of routine startup, never its execution. Configuration,
24
+ Bundler installation, dependency repairs, binstub generation and technical
25
+ diagnosis are WORKER work. Read owner state and public CLI contracts to route
26
+ the commission; source-code investigation, troubleshooting and reproduction
27
+ commands belong to the worker. Capture the observed symptom and desired
28
+ outcome. An unknown root cause is not a reason to postpone task creation and
29
+ dispatch. Create a commission and dispatch a separate lab worker even when the
30
+ project overseer cannot start yet. Do not edit project configuration, install
31
+ packages or run repair commands yourself. Missing workers are a concrete
32
+ capability gap, not a reason to become the worker.
33
+
23
34
  ## First turn after start
24
35
 
25
- 1. Read your own coordination tasks: `ace-task --in _overseer list`.
26
- 2. Read per-project readiness from the start report and the state owners
27
- (`ace-overseer status`); a project reported `blocked` is an escalation
28
- with its concrete reason, never something to work around by starting a
29
- duplicate session or doing the project's work yourself.
30
- 3. Re-run `ace-overseer start` to repair missing pieces only — it reuses
31
- healthy sessions and never restarts them or closes manual panes.
36
+ `ace-overseer start` is the bootstrap entry point. It launches your Pi
37
+ process directly in the current terminal and directory, with this Lab role
38
+ and context. It performs no Herdr agent, owner or layout preflight. A missing `.ace/overseer/config.yml` is first-run setup, not a request
39
+ for the Captain to write YAML. The packaged bootstrap profile is
40
+ `pi`, `zai/glm-5.3-flash`, thinking `high`; explicit profiles take precedence
41
+ and an invalid explicit configuration never silently falls back.
42
+
43
+ The Captain's latest instruction outranks this guide and stored tasks or plans.
44
+ On this first turn, commission any missing configuration and project
45
+ preparation through workers before resuming unrelated stored backlog. Read old
46
+ `_overseer` tasks as context; do not dispatch old auth, publication or full
47
+ acceptance work while the current instruction is bootstrap and project start.
48
+ Report scope conflicts to the host operator instead of negotiating away a new
49
+ Captain order.
50
+
51
+ 1. Read the lab topology, current private tasks and real assignment/session
52
+ state. Resume this commissioned bootstrap before unrelated backlog. Resolve
53
+ actual project paths; ask only about ambiguous scope or missing authority.
54
+ 2. Read `wfi://overseer/bootstrap-delegation` through `ace-bundle` and follow
55
+ its complete task → worker → observation → verification → start procedure.
56
+ 3. Arm observation with the `ace_eyes` tool, action `start`, using the lab's
57
+ eyes configuration path. Check enabled=true, breaker=null, errors=0 and
58
+ a successful observation before dispatch. A missing tool/configuration is
59
+ a readiness gap. Writing `/eyes` in prose does not arm observation.
60
+ 4. For a preparation commission, read existing readiness/session state; use
61
+ a startup dry run only if needed to establish an otherwise unknown status.
62
+ Do not investigate its implementation or reproduce the failure yourself.
63
+ Once the symptom is known, create/reconcile the task and dispatch its
64
+ worker. Run `ace-overseer start --reconcile` for that commission only after
65
+ accepted worker completion and independent verification. Bare
66
+ `ace-overseer start` launches a foreground harness; never call it
67
+ recursively from your own session.
68
+ 5. After dispatch, record the real assignment and agent identity and END YOUR
69
+ TURN. Do not sleep-poll, run repeated status commands, or wait synchronously
70
+ for the worker. A semantic change wakes you; unchanged state stays silent.
32
71
 
33
72
  ## Delegation and escalation
34
73
 
35
74
  - Route goals to a project by working through THAT project's overseer (its
36
75
  session is labeled `overseer-<project-root>`); you do not dispatch its
37
- coworkers directly.
76
+ coworkers directly for product work. Lab bootstrap workers are the explicit
77
+ exception: they prepare a commissioned project whose overseer cannot start.
38
78
  - Cross-project blockers (shared forge access, missing host capability, a
39
79
  project repeatedly failing) escalate to the Captain through `ace-hitl`
40
80
  with the per-project evidence.
@@ -80,6 +80,7 @@ task:
80
80
  ```bash
81
81
  ace-task create "Manage: <scope>" --in _overseer --tags queue
82
82
  ace-task create "Prepare <scope>" --child-of <manager-ref>
83
+ ace-task update <prep-ref> --set role=planner
83
84
  ace-task create "Implement <scope>" --child-of <manager-ref>
84
85
  ace-task create "Review <scope>" --child-of <manager-ref>
85
86
  ace-task create "Integrate <scope>" --child-of <manager-ref>
@@ -94,7 +95,11 @@ Rules:
94
95
  - Add worktree/assignment references only after they really exist (the
95
96
  planner prepares them); never fabricate references ahead of preparation.
96
97
  Record them on the step that owns them, e.g.
97
- `ace-task update <step-ref> --set worktree=.ace-wt/<task>/`.
98
+ `ace-task update <step-ref> --set assignment=<actual-id> --set role=<allocated-role> --set worktree=<actual-path>`.
99
+ Read back the fields; notes alone do not bind reports. `role=planner` denotes
100
+ only the allocation that prepares assignments, never bootstrap-worker or
101
+ confirmation of a running project. Resolve note folders from `ace-task show`;
102
+ never guess their title-derived paths.
98
103
 
99
104
  - Cross-task ordering goes through the integration step: a step of task B
100
105
  that requires A's merge depends on A's *integrate* subtask, not on A's
@@ -162,8 +167,9 @@ When a report arrives (ace-hitl event or message):
162
167
  1. Match its message ID plus task/assignment/step references to the current
163
168
  order. A report that fits no open allocation is kept for clarification,
164
169
  not counted as success.
165
- 2. Record the outcome and the processed report ID in the managing task /
166
- step (task-folder notes), then update statuses:
170
+ 2. Persist the exact accepted event ID and result on the owning step:
171
+ `ace-task update <step-ref> --set processed_report=<event-id> --set report_result=<result>`.
172
+ Add evidence notes in the folder returned by `ace-task show`, then update statuses:
167
173
  `ace-task update <step-ref> --set status=done` (or keep open / escalate).
168
174
  3. For success: end the current allocation, then continue with the next
169
175
  unblocked step per rule 3. For a repeated report: check the recorded
@@ -174,14 +180,23 @@ When a report arrives (ace-hitl event or message):
174
180
 
175
181
  `ace-overseer process-reports` executes rules 1-3 mechanically: it matches
176
182
  each incoming event (assignment recorded on a step, or the managing task's
177
- project_task with exactly one non-terminal step), records the outcome and
183
+ project_task with exactly one explicitly allocated `role=planner` non-terminal
184
+ step having no assignment). Task and any supplied role must agree; an event
185
+ without an ID is refused. Unassigned readiness never closes worker, verifier,
186
+ integration or confirm-start allocations. Before recording assigned success, the processor reads the actual coworker role
187
+ allocation and ace-assign state: exact task/assignment/role, a completed nonempty
188
+ plan, and every step done are required in dry-run and apply. Unavailable owner
189
+ state refuses acceptance. It records the outcome and
178
190
  the processed report ID on the step through the ordinary ace-task update
179
191
  surface, and continues with the next unblocked step through the existing
180
192
  gates — `ace-overseer handoff` for the next role when the family records a
181
193
  worktree, otherwise the `work-on` dependency gate. A repeated delivery is
182
194
  answered from the recorded `processed_report` and re-runs nothing; an error
183
195
  report or question never advances a step; a report matching no open
184
- allocation stays for clarification. `--dry-run` interprets without effects.
196
+ allocation stays for clarification. A `role=confirm-start` continuation remains
197
+ a coordinator operation; no generic worker is dispatched and no managing task
198
+ closes until first-turn and observation evidence is accepted. `--dry-run`
199
+ interprets without effects.
185
200
 
186
201
  ### 6) Close
187
202
 
@@ -15,7 +15,7 @@ module Ace
15
15
  # assignment that matches no step is :unmatched), or — only for
16
16
  # reports without an assignment (planner readiness) — by the
17
17
  # managing task's project_task plus exactly one non-terminal
18
- # step whose own assignment is blank (the preparation role). An
18
+ # step explicitly allocated to role planner with no assignment. An
19
19
  # event that fits no open allocation is :unmatched, kept
20
20
  # for clarification, never success (an ambiguous cross-manager
21
21
  # match is also :unmatched).
@@ -45,6 +45,8 @@ module Ace
45
45
  # recorded_result:}
46
46
  # {status: :unmatched, reason:}
47
47
  def self.evaluate(event:, managers:)
48
+ return {status: :unmatched, reason: "event has no report identity"} if event["id"].to_s.strip.empty?
49
+
48
50
  matched = match(event, managers)
49
51
  return {status: :unmatched, reason: unmatched_reason(event)} unless matched
50
52
 
@@ -142,16 +144,11 @@ module Ace
142
144
  # because a stale report for a different assignment must never
143
145
  # complete whichever step happens to remain.
144
146
  #
145
- # Without an assignment (a planner readiness report carries task
146
- # + result only) the report binds to the PREPARATION role alone:
147
- # the managing task's project_task must match the reported task
148
- # AND leave exactly one non-terminal step whose own assignment is
149
- # blank (the preparation step). A sole remaining step that is
150
- # bound to a role assignment belongs to that role, not to the
151
- # report — absence of an assignment is never evidence that
152
- # whichever role remains just finished. A match that is ambiguous
153
- # across managers (or across steps) fits no open allocation and
154
- # returns nil.
147
+ # Unassigned readiness can complete only an explicitly allocated
148
+ # planner step. A missing assignment says nothing about the role:
149
+ # confirm-start and bootstrap execution also have unassigned windows.
150
+ # Task identity and any supplied role must agree with the allocation.
151
+ # Ambiguous allocations never advance.
155
152
  #
156
153
  # @return [Hash{manager:, step:, terminal:}, nil]
157
154
  def self.match(event, managers)
@@ -161,8 +158,10 @@ module Ace
161
158
  assignment = event["assignment"].to_s
162
159
  if assignment != ""
163
160
  matches = managers.flat_map do |manager|
161
+ next [] unless task_agrees?(event, manager)
162
+
164
163
  steps_of(manager).filter_map do |step|
165
- {manager: manager, step: step} if step.metadata["assignment"].to_s == assignment
164
+ {manager: manager, step: step} if step.metadata["assignment"].to_s == assignment && role_agrees?(event, step)
166
165
  end
167
166
  end
168
167
  # No step records this assignment: unmatched, never a
@@ -182,7 +181,9 @@ module Ace
182
181
  next unless manager.metadata["project_task"].to_s == task && task != ""
183
182
 
184
183
  active = steps_of(manager).reject { |step| terminal?(step) }
185
- preparation = active.reject { |step| step.metadata["assignment"].to_s != "" }
184
+ preparation = active.select do |step|
185
+ step.metadata["assignment"].to_s.empty? && step.metadata["role"] == "planner" && role_agrees?(event, step)
186
+ end
186
187
  {manager: manager, step: preparation.first} if preparation.size == 1
187
188
  end
188
189
  return nil if matches.size > 1
@@ -201,7 +202,9 @@ module Ace
201
202
  def self.recorded_match(event, managers)
202
203
  matches = managers.flat_map do |manager|
203
204
  steps_of(manager).filter_map do |step|
204
- {manager: manager, step: step} if step.metadata[PROCESSED_REPORT_KEY] == event["id"]
205
+ {manager: manager, step: step} if step.metadata[PROCESSED_REPORT_KEY] == event["id"] &&
206
+ task_agrees?(event, manager) && role_agrees?(event, step) &&
207
+ (event["assignment"].to_s.empty? || step.metadata["assignment"].to_s == event["assignment"].to_s)
205
208
  end
206
209
  end
207
210
  return nil if matches.size != 1
@@ -210,6 +213,17 @@ module Ace
210
213
  terminal: terminal?(matches.first[:step])}
211
214
  end
212
215
 
216
+ def self.task_agrees?(event, manager)
217
+ expected = manager.metadata["project_task"].to_s
218
+ actual = event["task"].to_s
219
+ expected.empty? || expected == actual
220
+ end
221
+
222
+ def self.role_agrees?(event, step)
223
+ role = event["role"].to_s
224
+ role.empty? || step.metadata["role"].to_s == role
225
+ end
226
+
213
227
  # @return [String] why the event fit no open allocation
214
228
  def self.unmatched_reason(event)
215
229
  refs = []
@@ -3,14 +3,9 @@
3
3
  module Ace
4
4
  module Overseer
5
5
  module Atoms
6
- # Pure validation and normalization of the `start` contract
7
- # (task 8xs.t.pu0.1): the `.ace/overseer/config.yml` cascade must
8
- # carry an EXPLICIT start section — `scope: project|lab`, a
9
- # `profile` reference into the same document's `profiles` map and
10
- # an `instructions` source (wfi:// or an absolute file path).
11
- # Nothing is guessed: a missing or ambiguous section is an error
12
- # BEFORE any session is created, and no interim default model is
13
- # applied anywhere. Pure — no IO, value-free messages.
6
+ # Validate explicit start configuration, or select the packaged
7
+ # first-run profile when no start section exists. A malformed explicit
8
+ # configuration never falls back to another model or harness.
14
9
  class StartContract
15
10
  SCOPES = %w[project lab].freeze
16
11
  SECTION_KEYS = %w[scope profile instructions].freeze
@@ -23,7 +18,25 @@ module Ace
23
18
  # thinking:}, instructions:}
24
19
  # @raise [Ace::Overseer::Error] missing/ambiguous/invalid start
25
20
  # configuration
21
+ BOOTSTRAP_PROFILE = {"harness" => "pi", "model" => "zai/glm-5.3-flash",
22
+ "thinking" => "high"}.freeze
23
+
24
+ # A missing start configuration is first-run setup, not a reason to
25
+ # prevent the coordinator that owns setup from starting. Explicit
26
+ # configurations are still validated without fallback.
27
+ def self.bootstrap(config, scope: "lab")
28
+ return config if config.key?("start")
29
+
30
+ profiles = config.fetch("profiles", {})
31
+ raise Ace::Overseer::Error, "profiles must be a mapping" unless profiles.is_a?(Hash)
32
+
33
+ config.merge("start" => {"scope" => scope, "profile" => "overseer-default",
34
+ "instructions" => "wfi://overseer/#{(scope == "lab") ? "lab-start" : "start"}"},
35
+ "profiles" => {"overseer-default" => BOOTSTRAP_PROFILE}.merge(profiles))
36
+ end
37
+
26
38
  def self.normalize(config)
39
+ config = bootstrap(config)
27
40
  start = config["start"]
28
41
  unless start.is_a?(Hash)
29
42
  raise Ace::Overseer::Error,
@@ -36,13 +49,13 @@ module Ace
36
49
  unless unknown.empty?
37
50
  raise Ace::Overseer::Error,
38
51
  "start section has unknown key '#{unknown.sort.first}' " \
39
- "(allowed: #{SECTION_KEYS.join(', ')})"
52
+ "(allowed: #{SECTION_KEYS.join(", ")})"
40
53
  end
41
54
 
42
55
  scope = required(start, "scope")
43
56
  unless SCOPES.include?(scope)
44
57
  raise Ace::Overseer::Error,
45
- "start scope must be one of: #{SCOPES.join(', ')} (got '#{scope}')"
58
+ "start scope must be one of: #{SCOPES.join(", ")} (got '#{scope}')"
46
59
  end
47
60
 
48
61
  profile_name = required(start, "profile")
@@ -50,7 +63,7 @@ module Ace
50
63
 
51
64
  instructions = required(start, "instructions")
52
65
  unless INSTRUCTION_PROTOCOLS.any? { |prefix| instructions.start_with?(prefix) } ||
53
- instructions.start_with?("/")
66
+ instructions.start_with?("/")
54
67
  raise Ace::Overseer::Error,
55
68
  "start instructions must be a wfi:// (or prompt://, tmpl://) " \
56
69
  "source or an absolute file path"
@@ -81,7 +94,7 @@ module Ace
81
94
  unless unknown.empty?
82
95
  raise Ace::Overseer::Error,
83
96
  "profile '#{profile_name}' has unknown key '#{unknown.sort.first}' " \
84
- "(allowed: #{PROFILE_KEYS.join(', ')})"
97
+ "(allowed: #{PROFILE_KEYS.join(", ")})"
85
98
  end
86
99
 
87
100
  harness = required_value(raw, "harness", "profile '#{profile_name}'")