ace-coworker 0.6.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.
Files changed (77) hide show
  1. checksums.yaml +7 -0
  2. data/.ace-defaults/coworker/config.yml +6 -0
  3. data/.ace-defaults/coworker/roles/integrator.yml +15 -0
  4. data/.ace-defaults/coworker/roles/reviewer.yml +15 -0
  5. data/.ace-defaults/coworker/roles/spec.yml +14 -0
  6. data/.ace-defaults/coworker/roles/worker.yml +13 -0
  7. data/.ace-defaults/coworker/sequences/integrator.yml +20 -0
  8. data/.ace-defaults/coworker/sequences/reviewer.yml +20 -0
  9. data/.ace-defaults/coworker/sequences/spec.yml +16 -0
  10. data/.ace-defaults/coworker/sequences/worker.yml +21 -0
  11. data/.ace-defaults/nav/protocols/wfi-sources/ace-coworker.yml +19 -0
  12. data/CHANGELOG.md +255 -0
  13. data/README.md +98 -0
  14. data/Rakefile +13 -0
  15. data/docs/usage.md +564 -0
  16. data/exe/ace-coworker +16 -0
  17. data/handbook/workflow-instructions/coworker/integrator.wf.md +162 -0
  18. data/handbook/workflow-instructions/coworker/reviewer.wf.md +211 -0
  19. data/handbook/workflow-instructions/coworker/spec.wf.md +100 -0
  20. data/handbook/workflow-instructions/coworker/worker.wf.md +103 -0
  21. data/lib/ace/coworker/atoms/active_executor_rule.rb +71 -0
  22. data/lib/ace/coworker/atoms/brief_formatter.rb +33 -0
  23. data/lib/ace/coworker/atoms/config_schema.rb +121 -0
  24. data/lib/ace/coworker/atoms/integration_gate.rb +92 -0
  25. data/lib/ace/coworker/atoms/outcome_planner.rb +79 -0
  26. data/lib/ace/coworker/atoms/prepare_decision.rb +75 -0
  27. data/lib/ace/coworker/atoms/prompt_template.rb +28 -0
  28. data/lib/ace/coworker/atoms/report_record_formatter.rb +60 -0
  29. data/lib/ace/coworker/atoms/resume_brief_formatter.rb +84 -0
  30. data/lib/ace/coworker/atoms/resume_planner.rb +78 -0
  31. data/lib/ace/coworker/atoms/role_preset_schema.rb +91 -0
  32. data/lib/ace/coworker/atoms/round_record_schema.rb +62 -0
  33. data/lib/ace/coworker/atoms/round_rule.rb +105 -0
  34. data/lib/ace/coworker/cli/commands/commission.rb +100 -0
  35. data/lib/ace/coworker/cli/commands/gate.rb +91 -0
  36. data/lib/ace/coworker/cli/commands/prepare.rb +138 -0
  37. data/lib/ace/coworker/cli/commands/report.rb +79 -0
  38. data/lib/ace/coworker/cli/commands/resume.rb +57 -0
  39. data/lib/ace/coworker/cli/commands/roles.rb +60 -0
  40. data/lib/ace/coworker/cli/commands/rounds.rb +99 -0
  41. data/lib/ace/coworker/cli/commands/start.rb +39 -0
  42. data/lib/ace/coworker/cli/commands/status.rb +95 -0
  43. data/lib/ace/coworker/cli.rb +83 -0
  44. data/lib/ace/coworker/errors.rb +10 -0
  45. data/lib/ace/coworker/models/assignment_snapshot.rb +65 -0
  46. data/lib/ace/coworker/models/brief.rb +38 -0
  47. data/lib/ace/coworker/models/config.rb +54 -0
  48. data/lib/ace/coworker/models/outcome.rb +39 -0
  49. data/lib/ace/coworker/models/preparation.rb +67 -0
  50. data/lib/ace/coworker/models/resume_plan.rb +47 -0
  51. data/lib/ace/coworker/molecules/assignment_metadata.rb +57 -0
  52. data/lib/ace/coworker/molecules/assignment_probe.rb +57 -0
  53. data/lib/ace/coworker/molecules/config_loader.rb +119 -0
  54. data/lib/ace/coworker/molecules/git_state_probe.rb +63 -0
  55. data/lib/ace/coworker/molecules/hitl_reporter.rb +145 -0
  56. data/lib/ace/coworker/molecules/instruction_resolver.rb +82 -0
  57. data/lib/ace/coworker/molecules/project_root.rb +26 -0
  58. data/lib/ace/coworker/molecules/report_state_store.rb +53 -0
  59. data/lib/ace/coworker/molecules/review_round_store.rb +115 -0
  60. data/lib/ace/coworker/molecules/role_preset_loader.rb +95 -0
  61. data/lib/ace/coworker/molecules/role_sequence_composer.rb +245 -0
  62. data/lib/ace/coworker/molecules/step_evidence_reader.rb +60 -0
  63. data/lib/ace/coworker/molecules/step_report_reader.rb +39 -0
  64. data/lib/ace/coworker/molecules/task_probe.rb +40 -0
  65. data/lib/ace/coworker/molecules/task_record_writer.rb +44 -0
  66. data/lib/ace/coworker/molecules/worktree_executor_probe.rb +139 -0
  67. data/lib/ace/coworker/molecules/worktree_provision_probe.rb +137 -0
  68. data/lib/ace/coworker/organisms/commission_orchestrator.rb +148 -0
  69. data/lib/ace/coworker/organisms/prepare_orchestrator.rb +374 -0
  70. data/lib/ace/coworker/organisms/report_orchestrator.rb +192 -0
  71. data/lib/ace/coworker/organisms/resume_orchestrator.rb +91 -0
  72. data/lib/ace/coworker/organisms/start_config_writer.rb +127 -0
  73. data/lib/ace/coworker/organisms/start_orchestrator.rb +45 -0
  74. data/lib/ace/coworker/organisms/status_orchestrator.rb +62 -0
  75. data/lib/ace/coworker/version.rb +7 -0
  76. data/lib/ace/coworker.rb +86 -0
  77. metadata +319 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 288508c14f62358d53a0fe59f3a772ea024fa370201285151439e5ab93de88ff
4
+ data.tar.gz: 84e997a0876ad657f0caf39502c65e4d553110306f8b9fd63d83e6c7e5623fc8
5
+ SHA512:
6
+ metadata.gz: f73a2ccd21437dc1f44525ada59476246c7668abc4f9bfa26ca8356b8505447fd7bfc498a28baa8ad1ced52109f10b3871e53641e85cab4c249f1d0c8ed633b4
7
+ data.tar.gz: 4756deff6b2f919b3dfd307e17354605e4e5e5e4449a1a562f014d03045e26f083280efcb69598d49375c114775875a7f3d74e11c233721beabab78cac8a6642
@@ -0,0 +1,6 @@
1
+ # Defaults for ace-coworker (ADR-022 gem-defaults tier).
2
+ config_path: .ace-local/coworker/config.yml
3
+ reporting:
4
+ channel: hitl
5
+ errors:
6
+ on_failure: report
@@ -0,0 +1,15 @@
1
+ ---
2
+ # Integrator role preset (shipped gem defaults, overridable per project via
3
+ # .ace/coworker/roles/integrator.yml).
4
+ name: integrator
5
+ description: Merge gate for ready candidates; checks integrated dependencies, candidate-review head match, executed tests, and a fresh independent review verdict before merge, and withholds blocked merges
6
+ instructions: wfi://coworker/integrator
7
+ start_prompt: >-
8
+ Work as the {{role}} on task {{task}}: drive assignment {{assignment}} —
9
+ integrate the verified candidate after checking dependencies, current
10
+ changes, executed tests, and the independent review verdict, reporting the
11
+ actual outcome to the overseer at {{overseer}}.
12
+ reporting:
13
+ channel: hitl
14
+ errors:
15
+ on_failure: report
@@ -0,0 +1,15 @@
1
+ ---
2
+ # Reviewer role preset (shipped gem defaults, overridable per project via
3
+ # .ace/coworker/roles/reviewer.yml).
4
+ name: reviewer
5
+ description: Independent exact-candidate reviewer; fixes confirmed defects itself within its own assignment, checks the fix diff, and returns to full review rounds; escalates instead of marking unresolved High/Critical as success
6
+ instructions: wfi://coworker/reviewer
7
+ start_prompt: >-
8
+ Work as the {{role}} on task {{task}}: drive assignment {{assignment}} —
9
+ review the delivered change independently, fix confirmed defects yourself
10
+ inside this assignment, check each fix diff, and run full review rounds,
11
+ reporting to the overseer at {{overseer}}.
12
+ reporting:
13
+ channel: hitl
14
+ errors:
15
+ on_failure: report
@@ -0,0 +1,14 @@
1
+ ---
2
+ # Spec role preset (shipped gem defaults, overridable per project via
3
+ # .ace/coworker/roles/spec.yml).
4
+ name: spec
5
+ description: Creates or refines a complete behavior-first specification; significant unresolved gaps are reported, never guessed
6
+ instructions: wfi://coworker/spec
7
+ start_prompt: >-
8
+ Work as the {{role}} on task {{task}}: deliver or refine the complete
9
+ specification through assignment {{assignment}}, reporting to the overseer
10
+ at {{overseer}}.
11
+ reporting:
12
+ channel: hitl
13
+ errors:
14
+ on_failure: report
@@ -0,0 +1,13 @@
1
+ ---
2
+ # Worker role preset (shipped gem defaults, overridable per project via
3
+ # .ace/coworker/roles/worker.yml).
4
+ name: worker
5
+ description: Implements the commissioned change and verifies it; failed required tests block success
6
+ instructions: wfi://coworker/worker
7
+ start_prompt: >-
8
+ Work as the {{role}} on task {{task}}: drive assignment {{assignment}} to a
9
+ verified change, reporting to the overseer at {{overseer}}.
10
+ reporting:
11
+ channel: hitl
12
+ errors:
13
+ on_failure: report
@@ -0,0 +1,20 @@
1
+ ---
2
+ # Integrator role assignment process (shipped gem defaults, overridable
3
+ # per project via .ace/coworker/sequences/integrator.yml). Composed by the
4
+ # planner (ace-coworker prepare) into one ace-assign assignment for the
5
+ # integrator leg of the role sequence. The merge decision goes through
6
+ # the deterministic gate (ace-coworker gate /
7
+ # Ace::Coworker::Atoms::IntegrationGate).
8
+ role: integrator
9
+ description: "Integrator process for task {{task}}"
10
+ outcome: >-
11
+ The verified candidate for task {{task}} is merged, or the merge is
12
+ withheld with an explicit blocked gate verdict escalated to the
13
+ overseer.
14
+ steps:
15
+ - name: integrate-candidate
16
+ workflow: wfi://coworker/integrator
17
+ instructions:
18
+ - "Work as the integrator on task {{task}}: integrate the verified candidate after the reviewer assignment finished successfully."
19
+ - "Check `ace-coworker gate` with the candidate head, the reviewed head, the independent review verdict, the executed tests, and the integrated dependencies; an unknown fact is verified, never guessed."
20
+ - "Acceptance: a ready verdict merges the candidate (a merge that changes the candidate renews the checks and the review); a blocked verdict withholds the merge and escalates to the overseer via ace-hitl - withholding is a legitimate outcome, not a failure."
@@ -0,0 +1,20 @@
1
+ ---
2
+ # Reviewer role assignment process (shipped gem defaults, overridable per
3
+ # project via .ace/coworker/sequences/reviewer.yml). Composed by the
4
+ # planner (ace-coworker prepare) into one ace-assign assignment for the
5
+ # reviewer leg of the role sequence. The reviewer is independent of the
6
+ # worker and follows the same 3/2/10 round rule enforced by
7
+ # ace-coworker rounds record (Ace::Coworker::Atoms::RoundRule).
8
+ role: reviewer
9
+ description: "Independent reviewer process for task {{task}}"
10
+ outcome: >-
11
+ Independent review of the delivered change for task {{task}} accepted
12
+ under the 3/2/10 round rule, with all confirmed defects fixed and
13
+ fix diffs checked inside this assignment.
14
+ steps:
15
+ - name: review-rounds
16
+ workflow: wfi://coworker/reviewer
17
+ instructions:
18
+ - "Work as the reviewer on task {{task}}: review the delivered change independently of the worker; fix confirmed defects yourself inside this assignment and check each fix diff with a delta round."
19
+ - "Record every full round with `ace-coworker rounds record --type full` and every fix-diff check with `--type delta`; the RoundRule verdict decides the outcome, aborted or incomplete rounds are never clean."
20
+ - "Acceptance (3/2/10): at least 3 completed full rounds, the last 2 consecutive rounds clean (no confirmed High/Critical), and no unresolved earlier High/Critical; a rule-satisfying round 10 ends in success, no acceptance after 10 full rounds escalates to the overseer via ace-hitl."
@@ -0,0 +1,16 @@
1
+ ---
2
+ # Spec role assignment process (shipped gem defaults, overridable per
3
+ # project via .ace/coworker/sequences/spec.yml). Composed by the planner
4
+ # (ace-coworker prepare) into one ace-assign assignment for the spec leg
5
+ # of the role sequence.
6
+ role: spec
7
+ description: "Spec process for task {{task}}"
8
+ outcome: >-
9
+ Resolved requirements for task {{task}}: no material requirement gap is
10
+ left unresolved or guessed.
11
+ steps:
12
+ - name: clarify-requirements
13
+ workflow: wfi://coworker/spec
14
+ instructions:
15
+ - "Work as the spec role on task {{task}}: collect and resolve the requirement gaps that block implementation."
16
+ - "Acceptance: every material gap is either resolved from the task material or raised as an ace-hitl question to the overseer; guessing is never success."
@@ -0,0 +1,21 @@
1
+ ---
2
+ # Worker role assignment process (shipped gem defaults, overridable per
3
+ # project via .ace/coworker/sequences/worker.yml). Composed by the planner
4
+ # (ace-coworker prepare) into one ace-assign assignment for the worker leg
5
+ # of the role sequence.
6
+ role: worker
7
+ description: "Worker process for task {{task}}"
8
+ outcome: >-
9
+ Verified implementation of task {{task}} on the task branch: every
10
+ modified package passes its required tests (bin/ace-test <pkg> all) and
11
+ the work is committed.
12
+ steps:
13
+ - name: work-on-task
14
+ workflow: wfi://coworker/worker
15
+ instructions:
16
+ - "Work as the worker on task {{task}}: implement the commissioned change following the worker role instructions."
17
+ - "Acceptance: the required tests of every modified package pass; failed required tests block success (ace-assign fail), never a forced done."
18
+ - name: verify-test
19
+ instructions:
20
+ - "Run bin/ace-test <package> all for every modified package and record the real test counts in the task results file."
21
+ - "Acceptance: 0 failures across all modified packages."
@@ -0,0 +1,19 @@
1
+ ---
2
+ # WFI Sources Protocol Configuration for ace-coworker gem
3
+ # This enables workflow discovery from the installed ace-coworker gem
4
+
5
+ name: ace-coworker
6
+ type: gem
7
+ description: Coworker role workflow instructions from ace-coworker gem
8
+ priority: 10
9
+
10
+ # Configuration for workflow discovery within the gem
11
+ config:
12
+ # Relative path within the gem (default: handbook/workflow-instructions)
13
+ relative_path: handbook/workflow-instructions
14
+
15
+ # Pattern for finding workflow files (default: *.wf.md)
16
+ pattern: "*.wf.md"
17
+
18
+ # Enable discovery
19
+ enabled: true
data/CHANGELOG.md ADDED
@@ -0,0 +1,255 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+
11
+ ## [0.6.0] - 2026-10-20
12
+
13
+ ### Fixed
14
+
15
+ - Trust-posture parity with `ace-lab verify`: the instruction resolver
16
+ never executes the repository-controlled `bin/ace-nav` binstub under
17
+ a privileged (root) run — only the PATH-installed resolver is used.
18
+
19
+ - `ace-coworker prepare` no longer reports readiness for a protocol
20
+ instruction URI (`wfi://`, `prompt://`, `tmpl://`) that the ace-nav
21
+ resolver rejects in the prepared worktree. Protocol sources now resolve
22
+ through the SAME `InstructionResolver`/ace-nav path that `start` uses,
23
+ BEFORE readiness is claimed; a resolver that runs and fails is a
24
+ `role_instructions` gap (never ready), while a missing ace-nav CLI
25
+ (`InstructionResolver::NavUnavailableError`, ENOENT) stays a
26
+ non-blocking unknown consistent with lab verify's posture toward an
27
+ absent checker.
28
+
29
+ ### Added
30
+
31
+ - Readiness / gap reporting to the overseer in `ace-coworker prepare`
32
+ (8xg.t.sbz.3.3 / L4.4): every SUCCESSFUL preparation ends with a
33
+ READINESS report through ace-hitl (`--type report --result success`,
34
+ title `Preparation ready - <task>/<worktree-dir>`; a report expects
35
+ no reply) carrying the complete set to run the first step — worktree
36
+ (path/branch/disposition), every sequence leg, every start config,
37
+ and the exact first command (`ace-coworker start --config
38
+ .ace-local/coworker/prepare/<first-role>.yml` in the worktree) — so
39
+ the overseer never composes ace-assign details itself. Gaps never
40
+ pass as ready: role errors (unknown role, missing process
41
+ definition) become a `role_sequence` conflict and a missing overseer
42
+ address becomes a `missing_overseer` conflict — both exit 1, write
43
+ no start configs, and escalate to the overseer as a decision
44
+ question (the existing conflict path; question = a decision is
45
+ needed) with the concrete reasons: what is prepared, what is
46
+ missing, and the decision needed. The previous hard error `cannot
47
+ prepare start configs: no overseer address` is replaced by the
48
+ structured `missing_overseer` gap. The prepare result JSON/table
49
+ gained a `report` field (`{"kind": "readiness", "event": <id>,
50
+ "delivered": …}`, or the create/delivery failure under `error`); a
51
+ report delivery failure never undoes the preparation — the event id
52
+ stays available for an `ace-hitl send` retry. `--dry-run` reports
53
+ nothing (zero effects includes ace-hitl events). No new state owner:
54
+ events live with ace-hitl, helper state is none (ADR-034).
55
+ - Per-role executor start configs in `ace-coworker prepare`
56
+ (8xg.t.sbz.3.2 / L4.3): after composing the role-sequence assignments,
57
+ the planner also writes ONE start config per sequence leg into the
58
+ prepared worktree at `.ace-local/coworker/prepare/<role>.yml` — role,
59
+ instruction source, start prompt, task, assignment reference, overseer
60
+ address, and reporting/error rules — so `ace-coworker start --config
61
+ .ace-local/coworker/prepare/<role>.yml` (run inside the worktree)
62
+ begins a leg with zero ad-hoc setup. Ownership split stays one writer
63
+ per file: `prepare` owns `prepare/<role>.yml`, expanded through the
64
+ SAME commission primitive that writes the default `config.yml`, so the
65
+ round-trip guarantee ("what commission writes, start accepts") holds by
66
+ construction; `commission` remains the single writer of the default
67
+ config target. The leg configs require an overseer address (`--to`, or
68
+ the coworker config's `overseer` read leniently): a missing address
69
+ ends the preparation as a `missing_overseer` gap (see the L4.4 entry
70
+ above) instead of writing an incomplete config. Writing leg
71
+ configs never touches an active driver: the existing
72
+ active-executor/mismatched-worktree conflicts run first, and the
73
+ default `config.yml` is never written by prepare. Writes are
74
+ idempotent: identical leg configs are reported as `reused` without a
75
+ write, changed content as `updated`; `--dry-run` reports them as
76
+ `planned` with zero writes. New organism
77
+ `Ace::Coworker::Organisms::StartConfigWriter`; the prepare result
78
+ JSON/table gained a `start_configs` list (role, assignment, path,
79
+ disposition `created`/`reused`/`updated`/`planned`).
80
+ - Role-sequence assignment composition in `ace-coworker prepare`
81
+ (8xg.t.sbz.3.1 / L4.2): after finding or preparing the task worktree,
82
+ the planner composes the assignments for the WHOLE known role sequence in
83
+ one go — one `ace-assign` assignment per role in dependency order, stored
84
+ by ace-assign in the worktree's `.ace-local/assign/` (no second queue;
85
+ ADR-034) — so after start the roles hand off sequentially without the
86
+ overseer re-commissioning preparation per step. Each assignment records
87
+ the task id, its sequence position (`sequence N/M`), the expected outcome
88
+ of the leg, and — for every leg after the first — an explicit entry
89
+ condition naming the predecessor assignment and role. Per-role processes
90
+ come from new shipped sequence definitions overridable per project
91
+ (`.ace-defaults/coworker/sequences/<role>.yml`, project override
92
+ `.ace/coworker/sequences/<role>.yml`): worker (implementation plus
93
+ per-package `bin/ace-test` verification), spec (material requirement gaps
94
+ become `ace-hitl` questions, never guesses), reviewer (embeds the 3/2/10
95
+ round rule via `ace-coworker rounds record`: min 3 completed full rounds,
96
+ last 2 consecutive clean, no unresolved earlier High/Critical, max 10
97
+ then escalation), and integrator (runs the `ace-coworker gate` checks
98
+ before any merge; withholding is a legitimate outcome). A role without a
99
+ preset or without its own process definition is reported with exit 1 and
100
+ nothing is composed (all-or-nothing) — another role's process is never
101
+ substituted. Composition is idempotent: re-preparation reuses
102
+ already-composed assignments (matched by `<task>-<role>` name plus
103
+ recorded task_id) without writes; `--dry-run` composes nothing. New
104
+ molecule `Ace::Coworker::Molecules::RoleSequenceComposer`; the prepare
105
+ result JSON/table gained an ordered `assignments` list (role, position,
106
+ assignment id, disposition `created`/`existing`, step count, expected
107
+ outcome).
108
+
109
+ - Integrator role (8xg.t.sbz.4.3 / L5.2): the fourth coworker role preset
110
+ `integrator` (shipped in `.ace-defaults/coworker/roles/integrator.yml`,
111
+ workflow `wfi://coworker/integrator`). It performs the project-defined
112
+ integration: before merging it checks (a) dependencies are integrated
113
+ predecessors (an open PR or "work done" message never substitutes), (b)
114
+ the candidate head still matches the reviewed head (no drift), (c) tests
115
+ were executed and passed (real evidence; CI stays advisory), and (d) a
116
+ fresh independent review verdict accepts the EXACT candidate head. A
117
+ stale review after a candidate change, an unsatisfied dependency, or
118
+ missing test evidence WITHHOLDS the merge and escalates to the overseer
119
+ via `ace-hitl`; an uncertain operation outcome (merge/push) is verified
120
+ against the real state, never retried blind. A merge that changes the
121
+ candidate (conflict resolution) renews the checks and the review before
122
+ the result counts as integrated. The role drives git/ace-git; no merge
123
+ is performed in code. No new persisted artifact kind: integration
124
+ decisions persist in the assignment's existing report state.
125
+ - `ace-coworker gate`: deterministic pre-merge gate surface for the
126
+ integrator role over the new pure atom
127
+ `Ace::Coworker::Atoms::IntegrationGate`. `ace-coworker gate
128
+ --candidate-head <sha> --review-head <sha> --review-verdict
129
+ accept|continue|escalate --tests executed,passed
130
+ --dep <leaf>=integrated|missing [...]` evaluates the four checks and
131
+ prints `ready` or `blocked` with per-check reasons (dependencies,
132
+ candidate drift, stale/missing review evidence, executed+passing tests).
133
+ Unknown facts (omitted heads, missing sections) block with an explicit
134
+ verify-instead-of-guess reason rather than being assumed. `blocked` is a
135
+ legitimate gate outcome (exit 0); only malformed input fails - an invalid
136
+ `--dep` pair (missing `=`), a duplicate `--dep` name, or an unknown
137
+ `--tests` token (expected: executed, passed). Heads are recorded and
138
+ compared as full lowercase SHAs (case drift is tolerated, length mismatch
139
+ is not). Stateless: readiness only, no writes, no merges.
140
+
141
+ - `ace-coworker rounds record --assignment <id> --type full|delta --status
142
+ completed|aborted [--confirmed id:sev,...] [--resolved id,...]`: CLI
143
+ surface for the 3/2/10 enforcement (8xg.t.sbz.4.2) used by the reviewer
144
+ workflow. Appends one finished round to the coworker-owned history at
145
+ `.ace-local/coworker/review-rounds/<assignment>.json`
146
+ (`Molecules::ReviewRoundStore#record!`, validated at the boundary by
147
+ `Atoms::RoundRecordSchema`) and prints the resulting verdict with its
148
+ counters. A corrupt or non-array history file fails with `corrupt round
149
+ history at <path>` instead of silently resetting the round counters, and
150
+ the 10-round cap is terminal: a rule-satisfying state at round 11+
151
+ escalates instead of accepting.
152
+ - Review-round convergence enforcement (8xg.t.sbz.4.2 / L5.2): the 3/2/10
153
+ rule is now working code. `Ace::Coworker::Atoms::RoundRule` is a pure
154
+ evaluator over round records (type full|delta, status
155
+ completed|aborted, confirmed severities, resolved references) returning
156
+ an explicit verdict `:continue | :accept | :escalate` plus derived
157
+ counters (full rounds, completed full rounds, consecutive clean,
158
+ unresolved High/Critical). Minimum 3 full rounds with the last 2
159
+ consecutive clean and no unresolved earlier High/Critical accepts
160
+ (so clean/clean/clean and error/clean/clean both finish at round 3);
161
+ no acceptance after 10 full rounds escalates as an outcome, never an
162
+ exception. Delta/fix-diff rounds never advance the counters;
163
+ interrupted/aborted rounds are not clean and a confirmed High/Critical
164
+ resets the streak. `Molecules::ReviewRoundStore` persists the round
165
+ history per assignment in
166
+ `.ace-local/coworker/review-rounds/<assignment>.json` (the
167
+ coworker-owned location, following `ReportStateStore`), so a restart
168
+ reloads the counters and findings history instead of resetting them.
169
+ - Reviewer role (8xg.t.sbz.4.1 / L5.2): shipped preset
170
+ `.ace-defaults/coworker/roles/reviewer.yml` and the self-contained
171
+ `wfi://coworker/reviewer` workflow. The reviewer is independent of the
172
+ worker, fixes confirmed defects itself inside its own single assignment
173
+ (steps added via `ace-assign add`), checks each fix diff, and returns to
174
+ full review rounds under the 3/2/10 convergence rule (deterministic
175
+ enforcement landed as 8xg.t.sbz.4.2, see above). No effective fix or a
176
+ needed product decision is escalated via an `ace-hitl` decision question;
177
+ unresolved High/Critical is never marked as success.
178
+ - `ace-review` declared as a runtime dependency: the reviewer role's primary
179
+ function drives the `ace-review`/`ace-review-feedback` CLIs, matching the
180
+ gemspec's stated policy of declaring runtime CLI requirements.
181
+
182
+ ### Fixed
183
+
184
+ - `prepare --dry-run` is now zero-write on EXISTING worktrees too
185
+ (PR #393 audit): `PrepareOrchestrator` passes `dry_run` through to
186
+ `RoleSequenceComposer`, which resolves the whole sequence read-only —
187
+ already-composed legs are reported as `existing`, missing legs as
188
+ `planned` with no assignment id — and `StartConfigWriter` plans such
189
+ legs without commissioning them (a real run still requires a composed
190
+ assignment per leg). Previously a dry-run reuse/extension of an
191
+ existing worktree created real ace-assign assignments (e.g. a real
192
+ reviewer `assignment.yaml` after extending `--roles worker` to
193
+ `--roles worker,reviewer --dry-run`), mutating execution state during
194
+ a preview.
195
+ - `prepare` never reports readiness when a leg's instruction source does
196
+ not resolve (never-ready-on-missing-context, 8xg.t.sbz.3.2/.3.3):
197
+ before any start config is written or readiness reported, the
198
+ instruction source of EVERY leg is resolved through the existing
199
+ loader in the prepared worktree (file-path sources in-process; protocol
200
+ URIs stay delegated to ace-nav at start time). A missing source (e.g.
201
+ `instructions: roles/nonexistent.md`) is a new `role_instructions`
202
+ conflict — exit 1, no leg config written, escalated to the overseer as
203
+ a decision question — instead of a success whose emitted first-leg
204
+ start command fails immediately with "instruction file not found".
205
+ - `RoundRule` (3/2/10 review convergence): a completed delta round that
206
+ CONFIRMS a High/Critical finding now invalidates the prior clean
207
+ streak — even when the same delta (or a separate fix delta) resolves
208
+ the finding — so renewed clean full-round evidence is required before
209
+ `accept`. Previously three clean full rounds followed by a
210
+ High-confirmed delta (even resolved) still yielded `accept` with a
211
+ stale `consecutive_clean: 3`. Full-round counting (3/2/10 cap) is
212
+ unchanged; deltas without a confirmed High/Critical stay transparent.
213
+ - `RoleSequenceComposer` raises the actionable
214
+ `invalid assignment process` `Ace::Coworker::Error` for malformed
215
+ sequence step entries (e.g. a project override
216
+ `.ace/coworker/sequences/worker.yml` with `steps: [42]` or
217
+ `steps: [null]`) instead of a raw `TypeError`/`NoMethodError`, so
218
+ malformed user process data flows through the intended `role_sequence`
219
+ gap/HITL escalation in `prepare` instead of crashing it.
220
+ - `WorktreeExecutorProbe` cascade (8xi1p4z2): an unparseable nearest
221
+ cascade layer (e.g. unresolved merge-conflict markers in the
222
+ worktree's own `coworker/config.yml`) is now skipped per-layer,
223
+ exactly like a non-mapping layer, instead of discarding the whole
224
+ merge and silently reverting the probe to the default config
225
+ location — a commissioned executor at a cascade-overridden
226
+ `config_path` stays detected. The user-tier (`~/.ace`) override is
227
+ covered by a stubbed-HOME test (8xi1p4z8).
228
+ - `WorktreeExecutorProbe` cascade (8xi16mz3): a non-mapping cascade
229
+ layer (e.g. a `coworker/config.yml` containing a YAML list) is now
230
+ skipped instead of wiping the already-merged farther tiers, so valid
231
+ configuration (including a `config_path` override) from other tiers
232
+ survives. The probe's deliberate read-only asymmetry — following the
233
+ cascade-resolved `config_path` without the orchestrator's
234
+ project-root containment, since it only reads what the worktree's
235
+ loader process would read anyway — is now documented in the code
236
+ (8xi16mz4).
237
+ - Render start-prompt placeholders in a single pass derived from `PromptTemplate::PLACEHOLDERS`, so substituted values shaped like a later placeholder are never re-expanded.
238
+ - Raise a specific `invalid role preset` error for malformed YAML preset files (all `Psych::Exception` load failures), instead of a raw backtrace.
239
+ - Correct the spec role workflow's escalation command to the required `ace-hitl create "<title>" --type question ... --question "..."` form.
240
+ - `prepare` reads the target worktree's coworker config through the coworker
241
+ config cascade anchored at that worktree (project `.ace` tiers plus the
242
+ user tier), so a commission written under a configured `config_path`
243
+ (e.g. `.ace-local/coworker/worker.yml`) is detected as an active
244
+ executor instead of being missed because of the hard-coded default
245
+ location.
246
+ - `commission` canonicalizes the task identity before the assignment match
247
+ and the config write: a short task ref of the recorded task (e.g. `ccc`
248
+ for `8xh.t.ccc`) is accepted and the config stores the resolved full id,
249
+ while an assignment genuinely belonging to another task stays rejected.
250
+ - Reviewer workflow instruction (`wfi://coworker/reviewer`): newly named
251
+ fix steps are added via `ace-assign add --yaml <file> --assignment <id>`
252
+ (top-level `steps:` array with `name`/`instructions`, example included);
253
+ `--step` is documented as selecting an existing preset-catalog step
254
+ definition only — it cannot mint a new step name.
255
+
data/README.md ADDED
@@ -0,0 +1,98 @@
1
+ # ace-coworker
2
+
3
+ Prepared executor for the file-based ACE lab: `ace-coworker` reads the run
4
+ configuration under `.ace-local/coworker/`, validates it against the real task
5
+ and assignment in the current worktree, and renders the executor brief that
6
+ pins the assignment to drive. It is a composition tool in the spirit of
7
+ `ace-overseer`: it owns **only** `.ace-local/coworker/` and composes the
8
+ existing owners (`ace-task` ref resolution, `ace-assign` lifecycle via its CLI,
9
+ `ace-hitl` reporting via its CLI) without copying their state or adding a
10
+ second queue, journal, or daemon (ADR-034).
11
+
12
+ This is the new L3 file-based coworker; the historical `ace-coworker` gem was
13
+ renamed to `ace-assign` at v0.6.0 and there is no compatibility with old
14
+ `.cache/ace-coworker` paths (ADR-024).
15
+
16
+ ## Commands
17
+
18
+ ```
19
+ ace-coworker start [--config PATH] [--format table|json]
20
+ ace-coworker status [--config PATH] [--assignment ID] [--format table|json]
21
+ ace-coworker report [--result success|error] [--message TEXT] [--no-send] [--dry-run]
22
+ ace-coworker resume [--dry-run] # Resume interrupted work in this worktree
23
+ ace-coworker prepare --task REF --roles worker,reviewer [--to ADDR] [--dry-run]
24
+ ace-coworker roles # List role presets (gem + project)
25
+ ace-coworker commission --role worker --task REF --assignment ID --overseer ADDR
26
+ ace-coworker gate --candidate-head SHA --review-head SHA --review-verdict accept
27
+ --tests executed,passed --dep LEAF=integrated
28
+ ```
29
+
30
+ - `prepare` — the planner side: accept a preparation commission (task +
31
+ expected role sequence) and find or prepare exactly one proper worktree for
32
+ the task, THEN compose the assignments for the whole role sequence in one
33
+ go (L4.2): one `ace-assign` assignment per role in dependency order, stored
34
+ in the worktree's `.ace-local/assign/` with explicit entry conditions, the
35
+ expected outcome of each leg, and the role's process definition (shipped
36
+ `.ace-defaults/coworker/sequences/<role>.yml`, project override
37
+ `.ace/coworker/sequences/<role>.yml` — the reviewer leg embeds the 3/2/10
38
+ round rule, the integrator leg the `ace-coworker gate` checks). Re-preparing
39
+ reuses the worktree and the already-composed assignments without writes; an
40
+ active executor or a mismatched worktree escalates a decision question to
41
+ the overseer via `ace-hitl` instead of overwriting work; a role without its
42
+ own process is reported and nothing is composed — another role's process is
43
+ never substituted.
44
+
45
+ - `roles` / `commission` — role presets and the role-instantiation primitive
46
+ consumed by the planner (L4.2/L4.3 seam). Shipped presets: `worker`
47
+ (implement and verify; failed required tests block success), `spec`
48
+ (complete behavior-first specification; significant unresolved gaps are
49
+ reported via `ace-hitl`, never guessed), and `reviewer` (independent
50
+ review that fixes confirmed defects itself inside its own assignment,
51
+ checks each fix diff, and returns to full review rounds under the 3/2/10
52
+ convergence rule — escalating instead of marking unresolved High/Critical
53
+ as success), and `integrator` (result-dependent integration: merges only
54
+ candidates whose dependencies are integrated, whose head matches the
55
+ reviewed head, whose tests were executed and passed, and whose fresh
56
+ independent review verdict accepts the exact candidate; withheld merges
57
+ are blocked and escalated, never merged past the gate), backed by the
58
+ self-contained workflows `wfi://coworker/worker` / `wfi://coworker/spec` /
59
+ `wfi://coworker/reviewer` / `wfi://coworker/integrator`. `roles` lists
60
+ the catalog (gem defaults + project overrides in `.ace/coworker/roles/`);
61
+ `commission` expands a preset plus the commission identity into
62
+ `.ace-local/coworker/config.yml` — start-grade identity checks, atomic
63
+ write, overwrite refused without `--force`, `--dry-run` renders without
64
+ writing. Sequencing and active-driver guards stay with the planner.
65
+
66
+ - `gate` — the integrator role's deterministic pre-merge check
67
+ (`Ace::Coworker::Atoms::IntegrationGate`): evaluates candidate head vs
68
+ reviewed head (stale review), executed+passing tests, review verdict, and
69
+ per-dependency integration states, and prints `ready` or `blocked` with
70
+ per-check reasons. Pure and stateless — it decides readiness only; the
71
+ integrator role drives git/ace-git. `blocked` is a legitimate gate outcome
72
+ (exit 0); only invalid input fails.
73
+
74
+ - `start` — validate the prepared config (role, instructions, start prompt,
75
+ task, assignment, overseer, error rules), verify the task resolves in this
76
+ worktree and the assignment exists and matches the task, resolve the
77
+ instruction source, and print the executor brief. Writes nothing. Missing or
78
+ mismatched input fails with a specific `not ready:` / `invalid config:` /
79
+ mismatch error — it never guesses another commission and never creates a
80
+ substitute assignment or worktree.
81
+ - `status` — readiness query. Renders `not ready: .ace-local/coworker/config.yml
82
+ not found` (exit 0) when unprepared, otherwise the resolved identity,
83
+ assignment progress from `ace-assign status --format json`, and the
84
+ completion verdict (`complete` only when the assignment state is completed,
85
+ the plan is non-empty, and every step is done).
86
+
87
+ The config format consumed by the planner (L4) is documented in
88
+ [docs/usage.md](docs/usage.md).
89
+
90
+ ## Development
91
+
92
+ Tests: `bin/ace-test ace-coworker all` from the repository root. See
93
+ [CONTRIBUTING](../docs/ace-gems.g.md) for gem conventions (ATOM architecture,
94
+ ADR-022 config cascade, dry-cli commands).
95
+
96
+ ## License
97
+
98
+ MIT — see [LICENSE](../LICENSE).
data/Rakefile ADDED
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rake/testtask"
5
+
6
+ Rake::TestTask.new(:test) { |t|
7
+ t.libs << "test" << "lib"
8
+ t.test_files = FileList["test/**/*_test.rb"]
9
+ }
10
+
11
+ task :spec => :test
12
+
13
+ task default: :test