ace-assign 0.70.0 → 0.73.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 +4 -4
- data/.ace-defaults/assign/catalog/steps/auto-merge.step.yml +8 -8
- data/.ace-defaults/assign/catalog/steps/create-pr.step.yml +1 -1
- data/.ace-defaults/assign/catalog/steps/mark-pr-ready.step.yml +1 -1
- data/.ace-defaults/assign/config.yml +0 -13
- data/.ace-defaults/assign/presets/fix-bug.yml +1 -1
- data/.ace-defaults/assign/presets/work-on-task-ace-development.yml +1 -1
- data/.ace-defaults/assign/presets/work-on-task-auto-merge.yml +1 -1
- data/.ace-defaults/assign/presets/work-on-task.yml +1 -1
- data/CHANGELOG.md +3 -2099
- data/README.md +58 -31
- data/docs/exit-codes.md +36 -44
- data/docs/getting-started.md +9 -4
- data/docs/usage.md +129 -522
- data/handbook/skills/as-assign-drive/SKILL.md +1 -1
- data/handbook/workflow-instructions/assign/drive.wf.md +47 -118
- data/handbook/workflow-instructions/assign/prepare.wf.md +1 -1
- data/handbook/workflow-instructions/assign/verify-test-suite.wf.md +8 -2
- data/lib/ace/assign/cli/commands/assignment_target.rb +2 -15
- data/lib/ace/assign/cli/commands/create.rb +1 -8
- data/lib/ace/assign/cli/commands/fail.rb +0 -6
- data/lib/ace/assign/cli/commands/finish.rb +2 -23
- data/lib/ace/assign/cli/commands/fork_session.rb +0 -1
- data/lib/ace/assign/cli/commands/select.rb +0 -1
- data/lib/ace/assign/cli/commands/start.rb +0 -2
- data/lib/ace/assign/cli/commands/status.rb +1 -31
- data/lib/ace/assign/cli/commands/step.rb +1 -3
- data/lib/ace/assign/cli.rb +1 -85
- data/lib/ace/assign/errors.rb +8 -80
- data/lib/ace/assign/models/assignment.rb +5 -28
- data/lib/ace/assign/molecules/assignment_manager.rb +0 -26
- data/lib/ace/assign/molecules/fork_session_launcher.rb +4 -12
- data/lib/ace/assign/molecules/lifecycle_exclusion.rb +15 -112
- data/lib/ace/assign/molecules/runtime_control_surface_runner.rb +2 -1
- data/lib/ace/assign/organisms/assignment_executor.rb +0 -6
- data/lib/ace/assign/organisms/task_assignment_creator.rb +3 -8
- data/lib/ace/assign/version.rb +1 -1
- data/lib/ace/assign.rb +0 -6
- metadata +4 -161
- data/.ace-defaults/assign/presets/close-delivery.yml +0 -57
- data/.ace-defaults/assign/presets/deliver-release.yml +0 -60
- data/.ace-defaults/assign/presets/integrate-batch.yml +0 -72
- data/.ace-defaults/assign/presets/supervise-delivery.yml +0 -69
- data/docs/protected-authority.md +0 -282
- data/exe/ace-scope-ready +0 -55
- data/lib/ace/assign/atoms/assignment_scope.rb +0 -58
- data/lib/ace/assign/atoms/attempt_state_machine.rb +0 -84
- data/lib/ace/assign/atoms/delivery_parameters.rb +0 -19
- data/lib/ace/assign/atoms/evidence_digest.rb +0 -78
- data/lib/ace/assign/atoms/fixed_merge_schemas.rb +0 -398
- data/lib/ace/assign/authority/assignment_definition.rb +0 -35
- data/lib/ace/assign/authority/assignment_inventory.rb +0 -290
- data/lib/ace/assign/authority/campaign_consumer_policy.rb +0 -100
- data/lib/ace/assign/authority/campaign_execution.rb +0 -119
- data/lib/ace/assign/authority/campaign_round_transfer.rb +0 -82
- data/lib/ace/assign/authority/candidate_transfer.rb +0 -327
- data/lib/ace/assign/authority/cleanup_result_protection.rb +0 -53
- data/lib/ace/assign/authority/client.rb +0 -257
- data/lib/ace/assign/authority/deployment.rb +0 -627
- data/lib/ace/assign/authority/deployment_history.rb +0 -146
- data/lib/ace/assign/authority/endcap.rb +0 -455
- data/lib/ace/assign/authority/endcap_attempts.rb +0 -274
- data/lib/ace/assign/authority/endcap_campaign_results.rb +0 -232
- data/lib/ace/assign/authority/endcap_campaign_rounds.rb +0 -266
- data/lib/ace/assign/authority/endcap_contexts.rb +0 -23
- data/lib/ace/assign/authority/endcap_inboxes.rb +0 -37
- data/lib/ace/assign/authority/endcap_prepared_work.rb +0 -80
- data/lib/ace/assign/authority/endcap_publication.rb +0 -207
- data/lib/ace/assign/authority/endcap_results.rb +0 -398
- data/lib/ace/assign/authority/endcap_review_requests.rb +0 -183
- data/lib/ace/assign/authority/endcap_reviews.rb +0 -130
- data/lib/ace/assign/authority/endcap_service_settlement.rb +0 -152
- data/lib/ace/assign/authority/endcap_services.rb +0 -598
- data/lib/ace/assign/authority/evidence_transfer.rb +0 -67
- data/lib/ace/assign/authority/execution_scope_observation.rb +0 -903
- data/lib/ace/assign/authority/inbox_context_original.rb +0 -113
- data/lib/ace/assign/authority/launch_attempt_consumers.rb +0 -51
- data/lib/ace/assign/authority/launch_campaign_registration.rb +0 -214
- data/lib/ace/assign/authority/launch_control_channel.rb +0 -313
- data/lib/ace/assign/authority/launch_control_exclusions.rb +0 -127
- data/lib/ace/assign/authority/launch_driver.rb +0 -393
- data/lib/ace/assign/authority/launch_input_inhibition.rb +0 -132
- data/lib/ace/assign/authority/launch_lifecycle.rb +0 -997
- data/lib/ace/assign/authority/launch_prepared_work.rb +0 -122
- data/lib/ace/assign/authority/launch_review.rb +0 -91
- data/lib/ace/assign/authority/launch_scope_abort.rb +0 -81
- data/lib/ace/assign/authority/launch_scope_admission.rb +0 -215
- data/lib/ace/assign/authority/launch_scope_close.rb +0 -146
- data/lib/ace/assign/authority/launch_scope_parent.rb +0 -44
- data/lib/ace/assign/authority/launch_scope_release.rb +0 -859
- data/lib/ace/assign/authority/launch_steering.rb +0 -353
- data/lib/ace/assign/authority/launch_stop.rb +0 -254
- data/lib/ace/assign/authority/maintenance_workspace_retirement.rb +0 -229
- data/lib/ace/assign/authority/ordinary_attempt_start.rb +0 -137
- data/lib/ace/assign/authority/ordinary_client.rb +0 -70
- data/lib/ace/assign/authority/ordinary_completion.rb +0 -94
- data/lib/ace/assign/authority/ordinary_effect_settlement.rb +0 -118
- data/lib/ace/assign/authority/ordinary_lifecycle.rb +0 -191
- data/lib/ace/assign/authority/ordinary_peer.rb +0 -54
- data/lib/ace/assign/authority/ordinary_progress.rb +0 -162
- data/lib/ace/assign/authority/ordinary_queue.rb +0 -115
- data/lib/ace/assign/authority/ordinary_results.rb +0 -196
- data/lib/ace/assign/authority/ordinary_server.rb +0 -75
- data/lib/ace/assign/authority/original_inbox_selection.rb +0 -41
- data/lib/ace/assign/authority/posix_acl.rb +0 -59
- data/lib/ace/assign/authority/prepared_input.rb +0 -130
- data/lib/ace/assign/authority/prepared_queue.rb +0 -185
- data/lib/ace/assign/authority/prepared_task_context.rb +0 -116
- data/lib/ace/assign/authority/prepared_work.rb +0 -304
- data/lib/ace/assign/authority/prepared_worker.rb +0 -69
- data/lib/ace/assign/authority/private_directory.rb +0 -33
- data/lib/ace/assign/authority/protected_assignment_context.rb +0 -226
- data/lib/ace/assign/authority/readiness_hook.rb +0 -120
- data/lib/ace/assign/authority/receipt_transfer.rb +0 -48
- data/lib/ace/assign/authority/router.rb +0 -81
- data/lib/ace/assign/authority/server.rb +0 -131
- data/lib/ace/assign/authority/service_cleanup_dispatch.rb +0 -88
- data/lib/ace/assign/authority/service_cleanup_evidence.rb +0 -180
- data/lib/ace/assign/authority/service_delivery_evidence.rb +0 -101
- data/lib/ace/assign/authority/service_evidence.rb +0 -286
- data/lib/ace/assign/authority/service_publication_evidence.rb +0 -110
- data/lib/ace/assign/authority/socket_server.rb +0 -255
- data/lib/ace/assign/authority/task_context_entry.rb +0 -32
- data/lib/ace/assign/authority/transfer_codec.rb +0 -187
- data/lib/ace/assign/cli/commands/attempt/base.rb +0 -84
- data/lib/ace/assign/cli/commands/attempt/evidence.rb +0 -28
- data/lib/ace/assign/cli/commands/attempt/finish.rb +0 -51
- data/lib/ace/assign/cli/commands/attempt/reconcile.rb +0 -49
- data/lib/ace/assign/cli/commands/attempt/start.rb +0 -45
- data/lib/ace/assign/cli/commands/attempt/status.rb +0 -54
- data/lib/ace/assign/cli/commands/authority/inbox_context_principal.rb +0 -25
- data/lib/ace/assign/cli/commands/authority/inbox_context_selection.rb +0 -28
- data/lib/ace/assign/cli/commands/authority/launch.rb +0 -97
- data/lib/ace/assign/cli/commands/authority/serve.rb +0 -31
- data/lib/ace/assign/cli/commands/authority/status.rb +0 -26
- data/lib/ace/assign/cli/commands/authority/task_context.rb +0 -31
- data/lib/ace/assign/cli/commands/authority/task_context_principal.rb +0 -25
- data/lib/ace/assign/cli/commands/authority/task_context_selection.rb +0 -30
- data/lib/ace/assign/cli/commands/authority/terminate.rb +0 -29
- data/lib/ace/assign/cli/commands/authority/worker.rb +0 -23
- data/lib/ace/assign/cli/commands/campaign_export_result.rb +0 -55
- data/lib/ace/assign/cli/commands/campaign_record_round.rb +0 -57
- data/lib/ace/assign/cli/commands/delivery.rb +0 -107
- data/lib/ace/assign/cli/commands/inbox_bind.rb +0 -34
- data/lib/ace/assign/cli/commands/protected_submission.rb +0 -61
- data/lib/ace/assign/cli/commands/resume.rb +0 -38
- data/lib/ace/assign/cli/commands/submit_candidate.rb +0 -34
- data/lib/ace/assign/cli/commands/submit_result.rb +0 -61
- data/lib/ace/assign/models/attempt.rb +0 -178
- data/lib/ace/assign/models/attempt_binding.rb +0 -116
- data/lib/ace/assign/models/evidence_event.rb +0 -86
- data/lib/ace/assign/models/execution_receipt.rb +0 -139
- data/lib/ace/assign/molecules/attempt_reconciler.rb +0 -127
- data/lib/ace/assign/molecules/attempt_store.rb +0 -201
- data/lib/ace/assign/molecules/canonical_attempt_state.rb +0 -151
- data/lib/ace/assign/molecules/canonical_evidence.rb +0 -153
- data/lib/ace/assign/molecules/canonical_read_commands.rb +0 -84
- data/lib/ace/assign/molecules/canonical_read_snapshot.rb +0 -313
- data/lib/ace/assign/molecules/evidence_calculator.rb +0 -237
- data/lib/ace/assign/molecules/evidence_journal.rb +0 -1912
- data/lib/ace/assign/molecules/execution_identity_resolver.rb +0 -137
- data/lib/ace/assign/molecules/execution_scope_lineage.rb +0 -345
- data/lib/ace/assign/molecules/fixed_effect_reference.rb +0 -31
- data/lib/ace/assign/molecules/installed_journal_read.rb +0 -143
- data/lib/ace/assign/molecules/journal_input_inhibition.rb +0 -78
- data/lib/ace/assign/molecules/journal_mutation.rb +0 -273
- data/lib/ace/assign/molecules/journal_prompt_mutation.rb +0 -241
- data/lib/ace/assign/molecules/ordinary_merge_cli.rb +0 -68
- data/lib/ace/assign/molecules/ordinary_merge_contract.rb +0 -410
- data/lib/ace/assign/molecules/original_launch_binding.rb +0 -37
- data/lib/ace/assign/molecules/proposal_journal.rb +0 -179
- data/lib/ace/assign/molecules/protected_control_exclusion.rb +0 -303
- data/lib/ace/assign/molecules/protected_workspace_exclusion.rb +0 -330
- data/lib/ace/assign/molecules/protected_workspace_provisioner.rb +0 -164
- data/lib/ace/assign/molecules/receipt_verifier.rb +0 -314
- data/lib/ace/assign/molecules/terminal_scope_receipt.rb +0 -88
- data/lib/ace/assign/organisms/attempt_coordinator.rb +0 -1337
- data/lib/ace/assign/organisms/delivery_coordinator.rb +0 -342
- data/lib/ace/assign/organisms/ordinary_merge_consumer.rb +0 -365
- data/lib/ace/assign/organisms/prepared_work_builder.rb +0 -194
- data/lib/ace/assign/organisms/protected_delivery_coordinator.rb +0 -100
|
@@ -30,7 +30,7 @@ Hard stop rule:
|
|
|
30
30
|
- Treat `ace-assign status --assignment <id>@<root>` as the source of truth for fork completion; quiet terminal output is not enough reason to stop or declare a stall.
|
|
31
31
|
- If a prior terminal or drive session ended, re-enter from assignment state and continue from the next runnable work instead of depending on the old terminal handle.
|
|
32
32
|
- Before any final response, re-check pinned assignment status. If any runnable `pending` or `active` work remains, continue driving.
|
|
33
|
-
-
|
|
33
|
+
- Preserve unrelated dirty files; commit only task-owned changes.
|
|
34
34
|
- Use progress updates for partial status only.
|
|
35
35
|
- Return a final user-facing completion response only when the assignment is complete or the workflow reaches an explicit blocker/failure stop condition.
|
|
36
36
|
- If pending work remains runnable, continue driving.
|
|
@@ -12,8 +12,8 @@ doc-type: workflow
|
|
|
12
12
|
title: Drive Assignment Workflow
|
|
13
13
|
purpose: workflow instruction for driving ace-assign assignment execution
|
|
14
14
|
ace-docs:
|
|
15
|
-
last-updated: '2026-
|
|
16
|
-
last-checked: '2026-
|
|
15
|
+
last-updated: '2026-10-19'
|
|
16
|
+
last-checked: '2026-10-19'
|
|
17
17
|
---
|
|
18
18
|
|
|
19
19
|
# Drive Assignment Workflow
|
|
@@ -656,130 +656,54 @@ Follow the instructions directly, performing the described work:
|
|
|
656
656
|
|
|
657
657
|
**Agent Action:** Execute each instruction line as a task.
|
|
658
658
|
|
|
659
|
-
### 4.
|
|
660
|
-
|
|
661
|
-
Every external-facing step (implement, verify, review, merge, publish, deploy, release) runs inside a scoped attempt. The attempt -- not the report and not exit status -- is the delivery record.
|
|
662
|
-
|
|
663
|
-
For an original protected PreparedWorker, use its already admitted assignment,
|
|
664
|
-
attempt and selected scope. Do not run the local `attempt start`/receipt-file
|
|
665
|
-
sequence below, acquire another attempt, or execute an outer preset step. The
|
|
666
|
-
delivery step must already belong to the immutable captured subtree. Submit the
|
|
667
|
-
actual candidate and obtain the installed independent reviewer acceptance through
|
|
668
|
-
the protected commands supplied by the original drive prompt.
|
|
669
|
-
|
|
670
|
-
For an authorized protected merge, retain the exact approved head/candidate
|
|
671
|
-
generation, structured input file, installed receiver, authorization and stable
|
|
672
|
-
request ID. Read current authority generation for the first new request. Invoke
|
|
673
|
-
`ace-lab service request` with those original mapping/assignment/attempt/scope
|
|
674
|
-
selectors. Inspect `ace-lab service status` with the same request, input digest and
|
|
675
|
-
target, then consume succeeded canonical evidence with `ace-assign delivery
|
|
676
|
-
--operation merge --service-request REQUEST` and the same selectors. Include
|
|
677
|
-
`--artifact-digest` on status and consumption when the original target has one.
|
|
678
|
-
Exact retries retain the original generation, mutation/request ID and input bytes;
|
|
679
|
-
uncertainty never permits refreshing or resending an effect. The protected delivery
|
|
680
|
-
consumer verifies the imported receipt and canonical delivery event without another
|
|
681
|
-
provider mutation. Only that succeeded result permits finishing the active queue
|
|
682
|
-
step. Refusal, unavailable evidence or uncertainty leaves it unfinished and reports
|
|
683
|
-
the exact blocker. Credentials and queue completion do not replace authorization
|
|
684
|
-
or canonical evidence. The following local attempt sequence applies only to
|
|
685
|
-
ordinary standalone assignments.
|
|
686
|
-
|
|
687
|
-
**Step 1: Start the attempt before executing the step.** Actor identity is derived from the execution boundary; never pass actor flags.
|
|
659
|
+
### 4. Execute the Active Step Directly
|
|
688
660
|
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
echo "$ATTEMPT_JSON"
|
|
692
|
-
```
|
|
693
|
-
|
|
694
|
-
- A repeated identical start returns the same attempt; a conflicting start fails (exit 5). Never launch a second writer for an owned subtree.
|
|
695
|
-
- `base_head` is captured exactly once at start. Record the `attempt_id`.
|
|
696
|
-
|
|
697
|
-
**Step 2: Execute the step command(s).** If blocked, capture concrete evidence:
|
|
698
|
-
|
|
699
|
-
- command attempted
|
|
700
|
-
- exact error output
|
|
701
|
-
- why the step cannot proceed
|
|
702
|
-
|
|
703
|
-
Mark the step failed with evidence (do not report synthetic completion):
|
|
704
|
-
|
|
705
|
-
```bash
|
|
706
|
-
ace-assign fail --message "Command failed: <cmd>. Error: <exact stderr>" --assignment "$ASSIGNMENT_TARGET"
|
|
707
|
-
```
|
|
708
|
-
|
|
709
|
-
**Step 3: Submit a structured receipt -- never prose -- to close the attempt.**
|
|
710
|
-
|
|
711
|
-
```bash
|
|
712
|
-
cat > /tmp/attempt-receipt.json << 'EOF'
|
|
713
|
-
{
|
|
714
|
-
"attempt_id": "<ATTEMPT_ID>",
|
|
715
|
-
"assignment_id": "<ASSIGNMENT_ID>",
|
|
716
|
-
"project_id": "<PROJECT_ID>",
|
|
717
|
-
"scope": "<STEP_NUMBER>",
|
|
718
|
-
"operation": "implement",
|
|
719
|
-
"producer": {"actor": "<boundary-actor>", "role": "worker", "runtime": "<boundary-runtime>"},
|
|
720
|
-
"head": "<exact tested/reviewed HEAD sha>",
|
|
721
|
-
"verdict": "succeeded",
|
|
722
|
-
"artifacts": [{"path": "report.md", "sha256": "<sha256>"}],
|
|
723
|
-
"checks": [{"name": "ace-test", "verdict": "passed"}],
|
|
724
|
-
"review": {"reviewer": {"actor": "<independent-reviewer>", "runtime": "<reviewer-runtime>"}, "verdict": "approved", "head": "<same HEAD sha>"}
|
|
725
|
-
}
|
|
726
|
-
EOF
|
|
727
|
-
|
|
728
|
-
ace-assign attempt finish --attempt "$ATTEMPT_ID" --receipt /tmp/attempt-receipt.json
|
|
729
|
-
```
|
|
730
|
-
|
|
731
|
-
Receipt rules enforced by the coordinator:
|
|
732
|
-
|
|
733
|
-
- `succeeded` verdicts require verifiable artifact digests, passing checks, and trusted coordinator/service authority; worker runtimes may submit attributable results but cannot self-approve.
|
|
734
|
-
- Review approval requires an executed independent reviewer verdict for the exact current head; same author/reviewer and report-only existence are rejected.
|
|
735
|
-
- Receipts carrying credentials, environment dumps, or terminal output are rejected outright.
|
|
736
|
-
- External effects (`merge`, `publish`, `deploy`, `release`) additionally require an accepted independent review receipt for the current head. Taskless assignments cannot record external effects.
|
|
737
|
-
|
|
738
|
-
**Step 4: Handle interruptions by classifying and reconciling -- never by assuming.**
|
|
661
|
+
Execute the active step's instructions directly, run the checks it requires, and
|
|
662
|
+
record the real results in the step report.
|
|
739
663
|
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
-
|
|
747
|
-
|
|
748
|
-
|
|
664
|
+
- If the work is blocked, capture the command you ran, the exact error output,
|
|
665
|
+
and why the step cannot proceed, then fail the step with that evidence (see
|
|
666
|
+
[Handle Failures](#7-handle-failures)).
|
|
667
|
+
- Record actual test and review results for the exact candidate head in the
|
|
668
|
+
assignment report (or the project task folder) before advancing. A report or
|
|
669
|
+
exit code alone is not proof by itself; report only what was actually run.
|
|
670
|
+
- Never replay `merge`, `publish`, or `deploy` automatically. An uncertain
|
|
671
|
+
external effect is reconciled against the authoritative remote/owner first;
|
|
672
|
+
reconciliation never re-executes the effect by itself.
|
|
749
673
|
|
|
750
674
|
#### Integration Gate and Typed Outcomes (every integration invocation)
|
|
751
675
|
|
|
752
676
|
These gates apply at EVERY integration entry point — a native integrate
|
|
753
|
-
command
|
|
754
|
-
|
|
677
|
+
command or an assignment integration step — with shared contract validation so
|
|
678
|
+
no entry point bypasses them.
|
|
755
679
|
|
|
756
680
|
- Before any mutation, resolve FRESH repository, PR, candidate exact head,
|
|
757
681
|
target base/head, review/test evidence and the authorized executor; recheck
|
|
758
682
|
target/head immediately before the mutation. A detected race invalidates
|
|
759
683
|
eligibility for that invocation.
|
|
760
|
-
- The low-level
|
|
684
|
+
- The low-level integrator ENFORCES the gates and returns one typed
|
|
761
685
|
outcome: `merged`, `needs-rebase`, `blocked` or `uncertain`. It never
|
|
762
686
|
authors, rebases or reviews its own candidate. Relay alone is not
|
|
763
|
-
execution: the
|
|
687
|
+
execution: the integrating agent monitors the actual result and continuation.
|
|
764
688
|
- If the target (current main) is NOT an ancestor of the candidate head, the
|
|
765
|
-
outcome is `needs-rebase`: never merge and never silently rewrite. The
|
|
766
|
-
|
|
767
|
-
preservation) in the candidate's isolated worktree, obtains
|
|
768
|
-
exact-head checks plus independent review of the NEW head, updates
|
|
769
|
-
verifies remote candidate identity and resubmits. A common old base
|
|
770
|
-
NOT make sibling heads sequentially fast-forwardable.
|
|
771
|
-
- Integration is serial in PREPARATION as well as in effect: the
|
|
772
|
-
|
|
773
|
-
candidate — never a mass rebase of the remaining queue. Each
|
|
774
|
-
its turn: resolve fresh target main; delegate `wfi://git/rebase`
|
|
775
|
-
candidate's isolated worktree IF needed; run the applicable checks;
|
|
776
|
-
an INDEPENDENT EXPLICIT review of the resulting exact head (patch
|
|
777
|
-
may support a short delta review but never substitutes the explicit
|
|
778
|
-
independent head approval); verify the remote PR head/base; issue ONE
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
689
|
+
outcome is `needs-rebase`: never merge and never silently rewrite. The
|
|
690
|
+
integrating agent delegates `wfi://git/rebase` (as-git-rebase, including
|
|
691
|
+
CHANGELOG preservation) in the candidate's isolated worktree, obtains
|
|
692
|
+
refreshed exact-head checks plus independent review of the NEW head, updates
|
|
693
|
+
the PR, verifies remote candidate identity and resubmits. A common old base
|
|
694
|
+
does NOT make sibling heads sequentially fast-forwardable.
|
|
695
|
+
- Integration is serial in PREPARATION as well as in effect: the confirmed
|
|
696
|
+
integration result for one candidate causes preparation of ONLY the next
|
|
697
|
+
selected candidate — never a mass rebase of the remaining queue. Each
|
|
698
|
+
candidate, on its turn: resolve fresh target main; delegate `wfi://git/rebase`
|
|
699
|
+
in that candidate's isolated worktree IF needed; run the applicable checks;
|
|
700
|
+
obtain an INDEPENDENT EXPLICIT review of the resulting exact head (patch
|
|
701
|
+
identity may support a short delta review but never substitutes the explicit
|
|
702
|
+
independent head approval); verify the remote PR head/base; issue ONE scoped
|
|
703
|
+
integrator request; wait/reconcile the actual integration outcome; refresh
|
|
704
|
+
main; select and prepare ONLY the next candidate. Queued later PRs keep their
|
|
705
|
+
existing branches/heads untouched until their turn; prior batch work is never
|
|
706
|
+
rolled back or reset.
|
|
783
707
|
- `uncertain` triggers reconciliation against the original durable reference;
|
|
784
708
|
it never permits blind retry.
|
|
785
709
|
- Never push directly to main; never switch the canonical checkout to a topic
|
|
@@ -831,7 +755,9 @@ For a blocked step:
|
|
|
831
755
|
|
|
832
756
|
### 5. Write Report (Only After Real Execution)
|
|
833
757
|
|
|
834
|
-
After the
|
|
758
|
+
After executing the step (or failing it with concrete evidence), write a brief report summarizing what was accomplished. The report is the local record: state what was actually run and link or paste the actual test/review evidence for the exact head.
|
|
759
|
+
|
|
760
|
+
**Re-read state before every finish.** In forked assignment subtrees, queued child steps can auto-advance between status checks, and a report submitted against a stale view can land on the wrong step number. Immediately before every `ace-assign finish --message` (and every `ace-assign fail`), re-run `ace-assign status --assignment "$ASSIGNMENT_TARGET"` and confirm the step you are reporting on is still the active step. If the active step moved, re-target or re-plan the report instead of submitting it against the old step.
|
|
835
761
|
|
|
836
762
|
```bash
|
|
837
763
|
# Write report content to a temp file
|
|
@@ -842,20 +768,23 @@ Completed the setup step successfully:
|
|
|
842
768
|
|
|
843
769
|
- Installed all dependencies via npm install
|
|
844
770
|
- Configured PostgreSQL database connection
|
|
845
|
-
- Verified installation with health check
|
|
771
|
+
- Verified installation with health check (command + observed output)
|
|
846
772
|
|
|
847
773
|
All setup prerequisites are now satisfied.
|
|
848
774
|
EOF
|
|
849
775
|
|
|
776
|
+
# Re-check active state immediately before submitting the report
|
|
777
|
+
ace-assign status --assignment "$ASSIGNMENT_TARGET"
|
|
778
|
+
|
|
850
779
|
# Submit report to advance the queue
|
|
851
780
|
ace-assign finish --message /tmp/step-report.md --assignment "$ASSIGNMENT_TARGET"
|
|
852
781
|
```
|
|
853
782
|
|
|
854
783
|
Prohibited:
|
|
855
784
|
|
|
856
|
-
- Advancing a step
|
|
857
|
-
- Treating a written report, exit 0, or prose as proof
|
|
858
|
-
- Reporting
|
|
785
|
+
- Advancing a step that was not executed or whose result has no recorded evidence.
|
|
786
|
+
- Treating a written report, exit 0, or prose as proof when the required tests or review were not run.
|
|
787
|
+
- Reporting an uncertain external effect as complete; reconcile the original effect first.
|
|
859
788
|
|
|
860
789
|
### 6. Verify State Transition (Required)
|
|
861
790
|
|
|
@@ -1003,7 +932,7 @@ When executing a step with a `skill:` field:
|
|
|
1003
932
|
| Step fails | Attempt first, then use `fail` with command/error evidence; decide retry/add/ask |
|
|
1004
933
|
| Skill not found | Execute instructions directly without skill |
|
|
1005
934
|
| Unclear instructions | Ask user for clarification |
|
|
1006
|
-
| Provider/tool unavailable | For fork steps: see Provider-Unavailability Recovery. For inline steps:
|
|
935
|
+
| Provider/tool unavailable | For fork steps: see Provider-Unavailability Recovery. For inline steps: retry with an alternate model, then fail with evidence |
|
|
1007
936
|
|
|
1008
937
|
## Assignment State Reference
|
|
1009
938
|
|
|
@@ -334,7 +334,7 @@ steps:
|
|
|
334
334
|
|
|
335
335
|
### 8. Output Result
|
|
336
336
|
|
|
337
|
-
Default output: `<task>/jobs/<timestamp>-job.yml` (e.g., `.ace-task
|
|
337
|
+
Default output: `<task>/jobs/<timestamp>-job.yml` (e.g., `.ace-tasks/<task-folder>/jobs/k5abc123-job.yml`)
|
|
338
338
|
|
|
339
339
|
Custom output: Use `--output path/to/custom.yaml`
|
|
340
340
|
|
|
@@ -3,8 +3,8 @@ doc-type: workflow
|
|
|
3
3
|
title: Assign Verify Test Suite Workflow
|
|
4
4
|
purpose: Narrow deterministic verification contract for ace-assign orchestration
|
|
5
5
|
ace-docs:
|
|
6
|
-
last-updated: 2026-
|
|
7
|
-
last-checked: 2026-
|
|
6
|
+
last-updated: 2026-10-19
|
|
7
|
+
last-checked: 2026-10-19
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# Verify Test Suite Workflow
|
|
@@ -25,6 +25,12 @@ Do not run `ace-test-e2e` or `ace-test-e2e-suite` from this workflow.
|
|
|
25
25
|
4. Run `ace-test <package> all --profile 6` for each modified package.
|
|
26
26
|
5. Run `ace-test-suite --target all`.
|
|
27
27
|
|
|
28
|
+
## Hermetic Environment Rule (Forked Drive Sessions)
|
|
29
|
+
|
|
30
|
+
Package verification frequently runs inside forked assignment drive sessions, where the launcher exports fork-runtime variables (`ACE_ASSIGN_DEFAULT_TARGET`, `ACE_ASSIGN_CURRENT_ASSIGNMENT_ID`, `ACE_ASSIGN_CURRENT_FORK_ROOT`, `ACE_RUNTIME`, `ACE_ASSIGN_LAUNCH_MODE`, `ACE_ASSIGN_FORK_WINDOW`, `ACE_ASSIGN_CALLBACK_PANE`, `PROJECT_ROOT_PATH`) and ambient tmux session variables (`TMUX`, `TMUX_PANE`) may also be present. Do not scrub these by hand and never bypass the runner with raw `bundle exec rake`/`ruby` inside a forked subtree.
|
|
31
|
+
|
|
32
|
+
Always verify through `ace-test` / `ace-test-suite`: the deterministic test runner applies a hermetic environment policy that drops all ambient `ACE_*` and `LAB_*` runtime configuration (including every `ACE_ASSIGN_*` fork-runtime variable) before any test executes, in-process and for spawned subprocesses. Verification results are therefore identical whether the command runs from a clean shell or from inside a forked drive session; any other invocation forfeits that guarantee.
|
|
33
|
+
|
|
28
34
|
## Skip Guidance
|
|
29
35
|
|
|
30
36
|
Skip only when all modified files are documentation, retrospectives, task specs, or similarly non-runnable metadata.
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
-
require_relative "../../authority/protected_assignment_context"
|
|
3
2
|
|
|
4
3
|
module Ace
|
|
5
4
|
module Assign
|
|
@@ -12,16 +11,11 @@ module Ace
|
|
|
12
11
|
# - <assignment-id>@<step-number>
|
|
13
12
|
module AssignmentTarget
|
|
14
13
|
DEFAULT_TARGET_ENV = "ACE_ASSIGN_DEFAULT_TARGET"
|
|
15
|
-
Target = Struct.new(:assignment_id, :scope,
|
|
14
|
+
Target = Struct.new(:assignment_id, :scope, keyword_init: true)
|
|
16
15
|
View = Struct.new(:assignment, :state, :scoped_state, :active_steps, :next_step, :focus_step, :scope_root, keyword_init: true)
|
|
17
16
|
|
|
18
17
|
private
|
|
19
18
|
|
|
20
|
-
def refuse_protected_graph_mutation!(options)
|
|
21
|
-
context = @protected_assignment_context ||= Ace::Assign::Authority::ProtectedAssignmentContext.load
|
|
22
|
-
context.refuse_graph_mutation!(options: options)
|
|
23
|
-
end
|
|
24
|
-
|
|
25
19
|
def resolve_assignment_target(options)
|
|
26
20
|
assignment_raw = options[:assignment]
|
|
27
21
|
explicit_target = unless assignment_raw.nil? || assignment_raw.to_s.strip.empty?
|
|
@@ -35,13 +29,7 @@ module Ace
|
|
|
35
29
|
"does not match #{DEFAULT_TARGET_ENV}=#{target_identity(env_target)}"
|
|
36
30
|
end
|
|
37
31
|
|
|
38
|
-
|
|
39
|
-
context = @protected_assignment_context ||= Ace::Assign::Authority::ProtectedAssignmentContext.load
|
|
40
|
-
target.prepared_input = context.resolve(options: options, assignment_id: target.assignment_id, scope: target.scope)
|
|
41
|
-
if target.prepared_input && ![Status, Step, Start, Finish, Fail, Resume].any? { |command| is_a?(command) }
|
|
42
|
-
raise AttemptErrors::EvidenceUnavailable, "protected queue command requires a reviewed new prepared version and attempt"
|
|
43
|
-
end
|
|
44
|
-
target
|
|
32
|
+
explicit_target || env_target || Target.new(assignment_id: nil, scope: nil)
|
|
45
33
|
end
|
|
46
34
|
|
|
47
35
|
def parse_assignment_target(raw)
|
|
@@ -75,7 +63,6 @@ module Ace
|
|
|
75
63
|
end
|
|
76
64
|
|
|
77
65
|
def build_executor_for_target(target)
|
|
78
|
-
return Ace::Assign::Authority::PreparedExecutor.new(target.prepared_input) if target.prepared_input
|
|
79
66
|
return Organisms::AssignmentExecutor.new unless target.assignment_id
|
|
80
67
|
|
|
81
68
|
manager = Molecules::AssignmentManager.new
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
-
require "json"
|
|
3
2
|
|
|
4
3
|
module Ace
|
|
5
4
|
module Assign
|
|
@@ -12,7 +11,6 @@ module Ace
|
|
|
12
11
|
|
|
13
12
|
desc "Create a new workflow assignment"
|
|
14
13
|
|
|
15
|
-
option :delivery_parameters, desc: "JSON file with forge selection and explicit PR provenance (task mode)"
|
|
16
14
|
option :yaml, desc: "Path to job.yaml config file"
|
|
17
15
|
option :task, aliases: ["-t"], type: :array,
|
|
18
16
|
desc: "Task reference(s), repeatable and comma-separated"
|
|
@@ -21,17 +19,14 @@ module Ace
|
|
|
21
19
|
option :debug, aliases: ["-d"], type: :boolean, default: false, desc: "Show debug output"
|
|
22
20
|
|
|
23
21
|
def call(yaml: nil, task: nil, preset: nil, **options)
|
|
24
|
-
refuse_protected_graph_mutation!(options)
|
|
25
22
|
validate_modes!(yaml, task, preset)
|
|
26
|
-
raise Ace::Support::Cli::Error, "--delivery-parameters requires --task" if yaml && options[:delivery_parameters]
|
|
27
23
|
|
|
28
24
|
result = if yaml
|
|
29
25
|
Organisms::AssignmentExecutor.new.start(yaml)
|
|
30
26
|
else
|
|
31
27
|
Organisms::TaskAssignmentCreator.new.call(
|
|
32
28
|
task_refs: task,
|
|
33
|
-
preset_name: preset || Organisms::TaskAssignmentCreator::DEFAULT_PRESET
|
|
34
|
-
delivery_parameters: options[:delivery_parameters] && JSON.parse(File.read(options[:delivery_parameters]))
|
|
29
|
+
preset_name: preset || Organisms::TaskAssignmentCreator::DEFAULT_PRESET
|
|
35
30
|
)
|
|
36
31
|
end
|
|
37
32
|
|
|
@@ -40,8 +35,6 @@ module Ace
|
|
|
40
35
|
print_assignment_header(result[:assignment])
|
|
41
36
|
print_step_instructions(result[:current] || result[:state]&.next_workable)
|
|
42
37
|
end
|
|
43
|
-
rescue JSON::ParserError, Errno::ENOENT
|
|
44
|
-
raise Ace::Support::Cli::Error, "Delivery parameters file unavailable or invalid JSON"
|
|
45
38
|
rescue ArgumentError => e
|
|
46
39
|
raise Ace::Support::Cli::Error, e.message
|
|
47
40
|
end
|
|
@@ -12,8 +12,6 @@ module Ace
|
|
|
12
12
|
desc "Mark current step as failed"
|
|
13
13
|
|
|
14
14
|
option :message, aliases: ["-m"], required: true, desc: "Error message"
|
|
15
|
-
option :mapping, desc: "Installed protected launch mapping ID"
|
|
16
|
-
option :attempt, desc: "Original protected attempt ID"
|
|
17
15
|
option :assignment, desc: "Target specific assignment ID"
|
|
18
16
|
option :quiet, aliases: ["-q"], type: :boolean, default: false, desc: "Suppress non-essential output"
|
|
19
17
|
option :debug, aliases: ["-d"], type: :boolean, default: false, desc: "Show debug output"
|
|
@@ -30,10 +28,6 @@ module Ace
|
|
|
30
28
|
puts "Step #{failed.number} (#{failed.name}) marked as failed"
|
|
31
29
|
puts "Updated: #{File.basename(failed.file_path)}"
|
|
32
30
|
puts "Error: #{message}"
|
|
33
|
-
if target.prepared_input
|
|
34
|
-
puts "Further work requires a reviewed new prepared version and attempt."
|
|
35
|
-
return
|
|
36
|
-
end
|
|
37
31
|
puts
|
|
38
32
|
puts "Options:"
|
|
39
33
|
puts "- ace-assign add \"fix-step\" to add a fix step"
|
|
@@ -13,8 +13,6 @@ module Ace
|
|
|
13
13
|
|
|
14
14
|
argument :step, required: false, desc: "Step number to finish (active assignment only)"
|
|
15
15
|
option :message, aliases: ["-m"], desc: "Report content: string, file path, or pipe stdin"
|
|
16
|
-
option :mapping, desc: "Installed protected launch mapping ID"
|
|
17
|
-
option :attempt, desc: "Original protected attempt ID"
|
|
18
16
|
option :assignment, desc: "Target specific assignment ID"
|
|
19
17
|
option :quiet, aliases: ["-q"], type: :boolean, default: false, desc: "Suppress non-essential output"
|
|
20
18
|
option :debug, aliases: ["-d"], type: :boolean, default: false, desc: "Show debug output"
|
|
@@ -26,7 +24,7 @@ module Ace
|
|
|
26
24
|
|
|
27
25
|
target = resolve_assignment_target(options)
|
|
28
26
|
executor = build_executor_for_target(target)
|
|
29
|
-
report_content = resolve_report_content(options
|
|
27
|
+
report_content = resolve_report_content(options)
|
|
30
28
|
result = executor.finish_step(
|
|
31
29
|
report_content: report_content,
|
|
32
30
|
step_number: step,
|
|
@@ -74,27 +72,8 @@ module Ace
|
|
|
74
72
|
|
|
75
73
|
private
|
|
76
74
|
|
|
77
|
-
def resolve_report_content(options
|
|
75
|
+
def resolve_report_content(options)
|
|
78
76
|
message = options[:message]&.strip
|
|
79
|
-
if protected
|
|
80
|
-
limit = Ace::Assign::Authority::PreparedWork::MAX_TEXT
|
|
81
|
-
if message && !message.empty? && File.exist?(message)
|
|
82
|
-
return File.open(message, File::RDONLY | File::NOFOLLOW | File::NONBLOCK) do |file|
|
|
83
|
-
before = file.stat
|
|
84
|
-
raise Error, "Report input must be a bounded regular file" unless before.file? && before.size.between?(1, limit)
|
|
85
|
-
bytes = file.read(limit + 1)
|
|
86
|
-
after = file.stat
|
|
87
|
-
unless bytes.bytesize == before.size && [before.dev, before.ino, before.size, before.mtime, before.ctime] ==
|
|
88
|
-
[after.dev, after.ino, after.size, after.mtime, after.ctime]
|
|
89
|
-
raise Error, "Report input changed"
|
|
90
|
-
end
|
|
91
|
-
bytes
|
|
92
|
-
end
|
|
93
|
-
end
|
|
94
|
-
bytes = message && !message.empty? ? message : $stdin.read(limit + 1)
|
|
95
|
-
raise Error, "Report input exceeds captured text bound" unless bytes && bytes.bytesize.between?(1, limit)
|
|
96
|
-
return bytes
|
|
97
|
-
end
|
|
98
77
|
return File.read(message) if message && !message.empty? && File.exist?(message)
|
|
99
78
|
return message if message && !message.empty?
|
|
100
79
|
|
|
@@ -12,8 +12,6 @@ module Ace
|
|
|
12
12
|
desc "Start next workable pending step"
|
|
13
13
|
|
|
14
14
|
argument :step, required: false, desc: "Step number to start (active assignment only)"
|
|
15
|
-
option :mapping, desc: "Installed protected launch mapping ID"
|
|
16
|
-
option :attempt, desc: "Original protected attempt ID"
|
|
17
15
|
option :assignment, desc: "Target specific assignment ID"
|
|
18
16
|
option :quiet, aliases: ["-q"], type: :boolean, default: false, desc: "Suppress non-essential output"
|
|
19
17
|
option :debug, aliases: ["-d"], type: :boolean, default: false, desc: "Show debug output"
|
|
@@ -41,8 +41,6 @@ module Ace
|
|
|
41
41
|
option :format, desc: "Output format (table, json)", default: "table"
|
|
42
42
|
option :quiet, aliases: ["-q"], type: :boolean, default: false, desc: "Suppress non-essential output"
|
|
43
43
|
option :debug, aliases: ["-d"], type: :boolean, default: false, desc: "Show debug output"
|
|
44
|
-
option :mapping, desc: "Installed protected launch mapping ID"
|
|
45
|
-
option :attempt, desc: "Original protected attempt ID"
|
|
46
44
|
option :assignment, desc: "Show status for specific assignment ID"
|
|
47
45
|
option :all, aliases: ["-a"], type: :boolean, default: false, desc: "Include completed assignments in other assignments section"
|
|
48
46
|
|
|
@@ -87,14 +85,9 @@ module Ace
|
|
|
87
85
|
def status_to_h(assignment, state, active_steps, next_step, target:, scope_root:)
|
|
88
86
|
# Extract auto_merge config if present in assignment settings or preset
|
|
89
87
|
auto_merge = false
|
|
90
|
-
preset_name = Ace::Assign::Molecules::PresetInferrer.infer_from_assignment(assignment)
|
|
88
|
+
preset_name = Ace::Assign::Molecules::PresetInferrer.infer_from_assignment(assignment)
|
|
91
89
|
auto_merge = true if preset_name && preset_name.start_with?("work-on-task-auto-merge")
|
|
92
90
|
|
|
93
|
-
evidence = Ace::Assign::Molecules::EvidenceCalculator.calculate(
|
|
94
|
-
auto_merge: auto_merge,
|
|
95
|
-
assignment_id: assignment.id
|
|
96
|
-
)
|
|
97
|
-
|
|
98
91
|
payload = {
|
|
99
92
|
assignment: {
|
|
100
93
|
id: assignment.id,
|
|
@@ -108,9 +101,6 @@ module Ace
|
|
|
108
101
|
|
|
109
102
|
payload[:next_step] = step_to_h(next_step, effective_fork_provider: effective_fork_provider_for(next_step, scoped_fork_metadata_step(state, next_step, target.scope, scope_root))) if active_steps.empty? && next_step
|
|
110
103
|
|
|
111
|
-
# Merge exact head evidence into root payload
|
|
112
|
-
payload.merge!(evidence)
|
|
113
|
-
|
|
114
104
|
payload
|
|
115
105
|
end
|
|
116
106
|
|
|
@@ -137,10 +127,6 @@ module Ace
|
|
|
137
127
|
lines = []
|
|
138
128
|
lines.concat(compact_summary_lines(view.assignment, view.scoped_state, view.active_steps, view.next_step))
|
|
139
129
|
|
|
140
|
-
if !target.prepared_input && (attempt_line = compact_attempt_line(view.assignment.id))
|
|
141
|
-
lines.insert(1, attempt_line)
|
|
142
|
-
end
|
|
143
|
-
|
|
144
130
|
unless target.assignment_id
|
|
145
131
|
other_line = compact_other_assignments_line(view.assignment.id, include_completed: include_completed)
|
|
146
132
|
lines << other_line if other_line
|
|
@@ -149,22 +135,6 @@ module Ace
|
|
|
149
135
|
puts lines.take(10).join("\n")
|
|
150
136
|
end
|
|
151
137
|
|
|
152
|
-
# Active attempt summary projected from the coordinator authority.
|
|
153
|
-
def compact_attempt_line(assignment_id)
|
|
154
|
-
projection = Organisms::AttemptCoordinator.new.status(assignment_id)
|
|
155
|
-
return nil unless projection
|
|
156
|
-
|
|
157
|
-
base = projection["base_head"].to_s[0, 7]
|
|
158
|
-
candidate = projection["candidate_head"].to_s[0, 7]
|
|
159
|
-
line = "Attempt: #{projection['attempt_id']} #{projection['state']}"
|
|
160
|
-
line += " | base:#{base}" unless base.to_s.empty?
|
|
161
|
-
line += " | cand:#{candidate.empty? ? 'none' : candidate}"
|
|
162
|
-
line += " | unresolved: #{projection['unresolved_effects'].join(',')}" if projection["unresolved_effects"].any?
|
|
163
|
-
line
|
|
164
|
-
rescue Ace::Assign::Error, Ace::Support::Cli::Error
|
|
165
|
-
nil
|
|
166
|
-
end
|
|
167
|
-
|
|
168
138
|
def compact_summary_lines(assignment, state, active_steps, next_step)
|
|
169
139
|
lines = [
|
|
170
140
|
compact_assignment_line(assignment, state, active_steps, next_step),
|
|
@@ -12,8 +12,6 @@ module Ace
|
|
|
12
12
|
desc "Show instructions for the active, next, or explicit step"
|
|
13
13
|
|
|
14
14
|
argument :step, required: false, desc: "Exact step number to inspect"
|
|
15
|
-
option :mapping, desc: "Installed protected launch mapping ID"
|
|
16
|
-
option :attempt, desc: "Original protected attempt ID"
|
|
17
15
|
option :assignment, desc: "Target specific assignment ID"
|
|
18
16
|
option :quiet, aliases: ["-q"], type: :boolean, default: false, desc: "Suppress non-essential output"
|
|
19
17
|
option :debug, aliases: ["-d"], type: :boolean, default: false, desc: "Show debug output"
|
|
@@ -26,7 +24,7 @@ module Ace
|
|
|
26
24
|
return if options[:quiet]
|
|
27
25
|
|
|
28
26
|
if inspected
|
|
29
|
-
puts(
|
|
27
|
+
puts(inspected.instructions)
|
|
30
28
|
else
|
|
31
29
|
puts no_work_message(view)
|
|
32
30
|
end
|