ace-assign 0.71.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.
Files changed (195) hide show
  1. checksums.yaml +4 -4
  2. data/.ace-defaults/assign/catalog/steps/auto-merge.step.yml +8 -8
  3. data/.ace-defaults/assign/catalog/steps/create-pr.step.yml +1 -1
  4. data/.ace-defaults/assign/catalog/steps/mark-pr-ready.step.yml +1 -1
  5. data/.ace-defaults/assign/config.yml +0 -13
  6. data/.ace-defaults/assign/presets/fix-bug.yml +1 -1
  7. data/.ace-defaults/assign/presets/work-on-task-ace-development.yml +1 -1
  8. data/.ace-defaults/assign/presets/work-on-task-auto-merge.yml +1 -1
  9. data/.ace-defaults/assign/presets/work-on-task.yml +1 -1
  10. data/CHANGELOG.md +3 -2119
  11. data/README.md +58 -31
  12. data/docs/exit-codes.md +36 -44
  13. data/docs/getting-started.md +9 -4
  14. data/docs/usage.md +129 -522
  15. data/handbook/skills/as-assign-drive/SKILL.md +1 -4
  16. data/handbook/workflow-instructions/assign/drive.wf.md +47 -195
  17. data/handbook/workflow-instructions/assign/prepare.wf.md +1 -1
  18. data/handbook/workflow-instructions/assign/verify-test-suite.wf.md +8 -2
  19. data/lib/ace/assign/cli/commands/assignment_target.rb +2 -15
  20. data/lib/ace/assign/cli/commands/create.rb +1 -8
  21. data/lib/ace/assign/cli/commands/fail.rb +0 -6
  22. data/lib/ace/assign/cli/commands/finish.rb +2 -23
  23. data/lib/ace/assign/cli/commands/fork_session.rb +0 -1
  24. data/lib/ace/assign/cli/commands/select.rb +0 -1
  25. data/lib/ace/assign/cli/commands/start.rb +0 -2
  26. data/lib/ace/assign/cli/commands/status.rb +1 -31
  27. data/lib/ace/assign/cli/commands/step.rb +1 -3
  28. data/lib/ace/assign/cli.rb +1 -85
  29. data/lib/ace/assign/errors.rb +8 -80
  30. data/lib/ace/assign/models/assignment.rb +5 -28
  31. data/lib/ace/assign/molecules/assignment_manager.rb +0 -26
  32. data/lib/ace/assign/molecules/fork_session_launcher.rb +4 -12
  33. data/lib/ace/assign/molecules/lifecycle_exclusion.rb +15 -112
  34. data/lib/ace/assign/organisms/assignment_executor.rb +0 -6
  35. data/lib/ace/assign/organisms/task_assignment_creator.rb +3 -8
  36. data/lib/ace/assign/version.rb +1 -1
  37. data/lib/ace/assign.rb +0 -6
  38. metadata +4 -176
  39. data/.ace-defaults/assign/presets/close-delivery.yml +0 -57
  40. data/.ace-defaults/assign/presets/deliver-release.yml +0 -60
  41. data/.ace-defaults/assign/presets/integrate-batch.yml +0 -72
  42. data/.ace-defaults/assign/presets/supervise-delivery.yml +0 -69
  43. data/docs/protected-authority.md +0 -282
  44. data/exe/ace-scope-ready +0 -55
  45. data/lib/ace/assign/atoms/assignment_scope.rb +0 -58
  46. data/lib/ace/assign/atoms/attempt_state_machine.rb +0 -84
  47. data/lib/ace/assign/atoms/candidate_limits.rb +0 -20
  48. data/lib/ace/assign/atoms/delivery_parameters.rb +0 -19
  49. data/lib/ace/assign/atoms/evidence_digest.rb +0 -78
  50. data/lib/ace/assign/atoms/fixed_merge_schemas.rb +0 -398
  51. data/lib/ace/assign/atoms/git_blob_batch.rb +0 -59
  52. data/lib/ace/assign/authority/assignment_definition.rb +0 -35
  53. data/lib/ace/assign/authority/assignment_inventory.rb +0 -290
  54. data/lib/ace/assign/authority/campaign_consumer_policy.rb +0 -100
  55. data/lib/ace/assign/authority/campaign_execution.rb +0 -119
  56. data/lib/ace/assign/authority/campaign_round_transfer.rb +0 -82
  57. data/lib/ace/assign/authority/candidate_blob_batch.rb +0 -55
  58. data/lib/ace/assign/authority/candidate_head_comparison.rb +0 -139
  59. data/lib/ace/assign/authority/candidate_transfer.rb +0 -357
  60. data/lib/ace/assign/authority/cleanup_result_protection.rb +0 -53
  61. data/lib/ace/assign/authority/client.rb +0 -257
  62. data/lib/ace/assign/authority/command_execution.rb +0 -180
  63. data/lib/ace/assign/authority/deployment.rb +0 -627
  64. data/lib/ace/assign/authority/deployment_history.rb +0 -146
  65. data/lib/ace/assign/authority/endcap.rb +0 -457
  66. data/lib/ace/assign/authority/endcap_attempts.rb +0 -274
  67. data/lib/ace/assign/authority/endcap_campaign_results.rb +0 -232
  68. data/lib/ace/assign/authority/endcap_campaign_rounds.rb +0 -266
  69. data/lib/ace/assign/authority/endcap_contexts.rb +0 -23
  70. data/lib/ace/assign/authority/endcap_inboxes.rb +0 -37
  71. data/lib/ace/assign/authority/endcap_prepared_work.rb +0 -80
  72. data/lib/ace/assign/authority/endcap_publication.rb +0 -41
  73. data/lib/ace/assign/authority/endcap_results.rb +0 -398
  74. data/lib/ace/assign/authority/endcap_review_requests.rb +0 -183
  75. data/lib/ace/assign/authority/endcap_reviews.rb +0 -130
  76. data/lib/ace/assign/authority/endcap_service_context.rb +0 -38
  77. data/lib/ace/assign/authority/endcap_service_settlement.rb +0 -152
  78. data/lib/ace/assign/authority/evidence_transfer.rb +0 -67
  79. data/lib/ace/assign/authority/execution_scope_observation.rb +0 -903
  80. data/lib/ace/assign/authority/fixed_publication_lifecycle.rb +0 -176
  81. data/lib/ace/assign/authority/fixed_service_lifecycle.rb +0 -594
  82. data/lib/ace/assign/authority/inbox_context_original.rb +0 -113
  83. data/lib/ace/assign/authority/launch_attempt_consumers.rb +0 -51
  84. data/lib/ace/assign/authority/launch_campaign_registration.rb +0 -214
  85. data/lib/ace/assign/authority/launch_control_channel.rb +0 -313
  86. data/lib/ace/assign/authority/launch_control_exclusions.rb +0 -127
  87. data/lib/ace/assign/authority/launch_driver.rb +0 -393
  88. data/lib/ace/assign/authority/launch_input_inhibition.rb +0 -132
  89. data/lib/ace/assign/authority/launch_lifecycle.rb +0 -997
  90. data/lib/ace/assign/authority/launch_prepared_work.rb +0 -122
  91. data/lib/ace/assign/authority/launch_review.rb +0 -91
  92. data/lib/ace/assign/authority/launch_scope_abort.rb +0 -81
  93. data/lib/ace/assign/authority/launch_scope_admission.rb +0 -215
  94. data/lib/ace/assign/authority/launch_scope_close.rb +0 -146
  95. data/lib/ace/assign/authority/launch_scope_parent.rb +0 -44
  96. data/lib/ace/assign/authority/launch_scope_release.rb +0 -859
  97. data/lib/ace/assign/authority/launch_steering.rb +0 -353
  98. data/lib/ace/assign/authority/launch_stop.rb +0 -254
  99. data/lib/ace/assign/authority/maintenance_workspace_retirement.rb +0 -229
  100. data/lib/ace/assign/authority/ordinary_attempt_start.rb +0 -137
  101. data/lib/ace/assign/authority/ordinary_client.rb +0 -70
  102. data/lib/ace/assign/authority/ordinary_completion.rb +0 -104
  103. data/lib/ace/assign/authority/ordinary_effect_settlement.rb +0 -118
  104. data/lib/ace/assign/authority/ordinary_lifecycle.rb +0 -227
  105. data/lib/ace/assign/authority/ordinary_merge_evidence.rb +0 -81
  106. data/lib/ace/assign/authority/ordinary_peer.rb +0 -54
  107. data/lib/ace/assign/authority/ordinary_progress.rb +0 -162
  108. data/lib/ace/assign/authority/ordinary_queue.rb +0 -115
  109. data/lib/ace/assign/authority/ordinary_release_artifacts.rb +0 -143
  110. data/lib/ace/assign/authority/ordinary_results.rb +0 -206
  111. data/lib/ace/assign/authority/ordinary_review_evidence.rb +0 -180
  112. data/lib/ace/assign/authority/ordinary_reviews.rb +0 -214
  113. data/lib/ace/assign/authority/ordinary_server.rb +0 -75
  114. data/lib/ace/assign/authority/ordinary_supervisor.rb +0 -99
  115. data/lib/ace/assign/authority/original_inbox_selection.rb +0 -41
  116. data/lib/ace/assign/authority/posix_acl.rb +0 -59
  117. data/lib/ace/assign/authority/prepared_input.rb +0 -130
  118. data/lib/ace/assign/authority/prepared_queue.rb +0 -185
  119. data/lib/ace/assign/authority/prepared_task_context.rb +0 -116
  120. data/lib/ace/assign/authority/prepared_work.rb +0 -309
  121. data/lib/ace/assign/authority/prepared_worker.rb +0 -69
  122. data/lib/ace/assign/authority/private_directory.rb +0 -33
  123. data/lib/ace/assign/authority/protected_assignment_context.rb +0 -226
  124. data/lib/ace/assign/authority/readiness_hook.rb +0 -120
  125. data/lib/ace/assign/authority/receipt_transfer.rb +0 -48
  126. data/lib/ace/assign/authority/release_artifact_manifest.rb +0 -91
  127. data/lib/ace/assign/authority/retained_input.rb +0 -53
  128. data/lib/ace/assign/authority/router.rb +0 -81
  129. data/lib/ace/assign/authority/server.rb +0 -131
  130. data/lib/ace/assign/authority/service_cleanup_dispatch.rb +0 -88
  131. data/lib/ace/assign/authority/service_cleanup_evidence.rb +0 -180
  132. data/lib/ace/assign/authority/service_delivery_evidence.rb +0 -101
  133. data/lib/ace/assign/authority/service_evidence.rb +0 -286
  134. data/lib/ace/assign/authority/service_publication_evidence.rb +0 -110
  135. data/lib/ace/assign/authority/socket_server.rb +0 -255
  136. data/lib/ace/assign/authority/task_context_entry.rb +0 -32
  137. data/lib/ace/assign/authority/transfer_codec.rb +0 -189
  138. data/lib/ace/assign/cli/commands/attempt/base.rb +0 -84
  139. data/lib/ace/assign/cli/commands/attempt/evidence.rb +0 -28
  140. data/lib/ace/assign/cli/commands/attempt/finish.rb +0 -51
  141. data/lib/ace/assign/cli/commands/attempt/reconcile.rb +0 -49
  142. data/lib/ace/assign/cli/commands/attempt/start.rb +0 -45
  143. data/lib/ace/assign/cli/commands/attempt/status.rb +0 -54
  144. data/lib/ace/assign/cli/commands/authority/inbox_context_principal.rb +0 -25
  145. data/lib/ace/assign/cli/commands/authority/inbox_context_selection.rb +0 -28
  146. data/lib/ace/assign/cli/commands/authority/launch.rb +0 -97
  147. data/lib/ace/assign/cli/commands/authority/serve.rb +0 -31
  148. data/lib/ace/assign/cli/commands/authority/status.rb +0 -26
  149. data/lib/ace/assign/cli/commands/authority/task_context.rb +0 -31
  150. data/lib/ace/assign/cli/commands/authority/task_context_principal.rb +0 -25
  151. data/lib/ace/assign/cli/commands/authority/task_context_selection.rb +0 -30
  152. data/lib/ace/assign/cli/commands/authority/terminate.rb +0 -29
  153. data/lib/ace/assign/cli/commands/authority/worker.rb +0 -23
  154. data/lib/ace/assign/cli/commands/campaign_export_result.rb +0 -55
  155. data/lib/ace/assign/cli/commands/campaign_record_round.rb +0 -57
  156. data/lib/ace/assign/cli/commands/delivery.rb +0 -107
  157. data/lib/ace/assign/cli/commands/inbox_bind.rb +0 -34
  158. data/lib/ace/assign/cli/commands/protected_submission.rb +0 -61
  159. data/lib/ace/assign/cli/commands/resume.rb +0 -38
  160. data/lib/ace/assign/cli/commands/submit_candidate.rb +0 -34
  161. data/lib/ace/assign/cli/commands/submit_result.rb +0 -61
  162. data/lib/ace/assign/models/attempt.rb +0 -178
  163. data/lib/ace/assign/models/attempt_binding.rb +0 -116
  164. data/lib/ace/assign/models/evidence_event.rb +0 -86
  165. data/lib/ace/assign/models/execution_receipt.rb +0 -139
  166. data/lib/ace/assign/molecules/attempt_reconciler.rb +0 -127
  167. data/lib/ace/assign/molecules/attempt_store.rb +0 -201
  168. data/lib/ace/assign/molecules/canonical_attempt_state.rb +0 -151
  169. data/lib/ace/assign/molecules/canonical_evidence.rb +0 -170
  170. data/lib/ace/assign/molecules/canonical_read_commands.rb +0 -84
  171. data/lib/ace/assign/molecules/canonical_read_snapshot.rb +0 -313
  172. data/lib/ace/assign/molecules/evidence_calculator.rb +0 -237
  173. data/lib/ace/assign/molecules/evidence_journal.rb +0 -1899
  174. data/lib/ace/assign/molecules/execution_identity_resolver.rb +0 -137
  175. data/lib/ace/assign/molecules/execution_scope_lineage.rb +0 -345
  176. data/lib/ace/assign/molecules/fixed_effect_reference.rb +0 -31
  177. data/lib/ace/assign/molecules/installed_journal_read.rb +0 -143
  178. data/lib/ace/assign/molecules/journal_input_inhibition.rb +0 -78
  179. data/lib/ace/assign/molecules/journal_mutation.rb +0 -274
  180. data/lib/ace/assign/molecules/journal_prompt_mutation.rb +0 -241
  181. data/lib/ace/assign/molecules/ordinary_merge_cli.rb +0 -68
  182. data/lib/ace/assign/molecules/ordinary_merge_contract.rb +0 -410
  183. data/lib/ace/assign/molecules/original_launch_binding.rb +0 -37
  184. data/lib/ace/assign/molecules/proposal_journal.rb +0 -179
  185. data/lib/ace/assign/molecules/protected_control_exclusion.rb +0 -303
  186. data/lib/ace/assign/molecules/protected_workspace_exclusion.rb +0 -330
  187. data/lib/ace/assign/molecules/protected_workspace_provisioner.rb +0 -164
  188. data/lib/ace/assign/molecules/receipt_verifier.rb +0 -320
  189. data/lib/ace/assign/molecules/terminal_scope_receipt.rb +0 -88
  190. data/lib/ace/assign/organisms/attempt_coordinator.rb +0 -1374
  191. data/lib/ace/assign/organisms/delivery_coordinator.rb +0 -342
  192. data/lib/ace/assign/organisms/ordinary_driver.rb +0 -310
  193. data/lib/ace/assign/organisms/ordinary_merge_consumer.rb +0 -365
  194. data/lib/ace/assign/organisms/prepared_work_builder.rb +0 -194
  195. data/lib/ace/assign/organisms/protected_delivery_coordinator.rb +0 -100
@@ -1,28 +0,0 @@
1
- # frozen_string_literal: true
2
- require_relative "base"
3
- module Ace
4
- module Assign
5
- module CLI
6
- module Commands
7
- module Attempt
8
- class Evidence < Ace::Support::Cli::Command
9
- include Attempt::Base
10
- desc "Read coordinator-accepted live execution or historical execution authority"
11
- option :attempt, required: true, desc: "Accepted execution attempt ID"
12
- option :receipt_digest, required: true, desc: "Accepted receipt digest"
13
- option :kind, default: "check", desc: "Evidence purpose: check, review-collection or review-approval"
14
- option :check_name, default: "tests", desc: "Required check name (tests binds operation test)"
15
- option :historical_head, desc: "Exact recorded head for historical authority only (never current-head evidence)"
16
- option :format, default: "json", desc: "JSON evidence projection"
17
-
18
- def call(**options)
19
- raise Ace::Support::Cli::Error, "evidence supports --format json" unless options[:format] == "json"
20
- emit_json(build_coordinator.evidence(attempt_id: options[:attempt], receipt_digest: options[:receipt_digest],
21
- kind: options[:kind], check_name: options[:check_name], historical_head: options[:historical_head]))
22
- end
23
- end
24
- end
25
- end
26
- end
27
- end
28
- end
@@ -1,51 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "json"
4
- require_relative "base"
5
-
6
- module Ace
7
- module Assign
8
- module CLI
9
- module Commands
10
- module Attempt
11
- # Protected completion selects an already submitted canonical result.
12
- # Ordinary local completion accepts its structured receipt file.
13
- class Finish < Ace::Support::Cli::Command
14
- include Ace::Support::Cli::Base
15
- include Attempt::Base
16
-
17
- desc "Finish a protected canonical result or an ordinary local receipt"
18
-
19
- option :attempt, desc: "Attempt ID"
20
- option :mapping, desc: "Exact installed protected mapping ID"
21
- option :assignment, desc: "Exact protected assignment ID"
22
- option :mutation, desc: "Stable original authority mutation ID"
23
- option :expected_generation, desc: "Original authority mutation generation"
24
- option :receipt, desc: "Path to the ordinary local receipt JSON file"
25
- option :result, desc: "Already submitted canonical protected result ID"
26
- option :head, desc: "Exact canonical candidate head"
27
- option :candidate_generation, desc: "Original canonical candidate generation"
28
-
29
- def call(**options)
30
- if (context = protected_context(options))
31
- raise Ace::Support::Cli::Error, "Protected finish forbids --receipt" unless options[:receipt].to_s.empty?
32
- usage = "finish --mapping MAP --assignment ID --attempt ID --result ID --head SHA --candidate-generation N --mutation ID --expected-generation N"
33
- client, params, mutation = protected_attempt_request(context, options, usage)
34
- params.merge!("result_id" => require_option(options, :result, usage), "head" => require_option(options, :head, usage),
35
- "candidate_generation" => integer_option(options, :candidate_generation, usage, positive: true))
36
- emit_json(protected_call(client, "finish", params, mutation))
37
- return
38
- end
39
- attempt_id = require_option(options, :attempt, "finish --attempt ID --receipt FILE")
40
- receipt = require_option(options, :receipt, "finish --attempt ID --receipt FILE")
41
-
42
- result = build_coordinator.finish(attempt_id: attempt_id, receipt_path: receipt)
43
-
44
- emit_json(result.projection)
45
- end
46
- end
47
- end
48
- end
49
- end
50
- end
51
- end
@@ -1,49 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "json"
4
- require_relative "base"
5
-
6
- module Ace
7
- module Assign
8
- module CLI
9
- module Commands
10
- module Attempt
11
- # Classify interruptions and resolve uncertainty against verified,
12
- # boundary-attributed receipts. Never replays external effects.
13
- class Reconcile < Ace::Support::Cli::Command
14
- include Ace::Support::Cli::Base
15
- include Attempt::Base
16
-
17
- desc "Reconcile an interrupted or uncertain attempt"
18
-
19
- option :attempt, desc: "Attempt ID"
20
- option :mapping, desc: "Exact installed protected mapping ID"
21
- option :assignment, desc: "Exact protected assignment ID"
22
- option :mutation, desc: "Stable original authority mutation ID"
23
- option :expected_generation, desc: "Original authority mutation generation"
24
- option :receipt, desc: "Path to the receipt JSON file (required to resolve uncertainty)"
25
-
26
- def call(**options)
27
- if (context = protected_context(options))
28
- raise Ace::Support::Cli::Error, "Protected recovery forbids --receipt" unless options[:receipt].to_s.empty?
29
- usage = "reconcile --mapping MAP --assignment ID --attempt ID --mutation ID --expected-generation N"
30
- client, params, mutation = protected_attempt_request(context, options, usage)
31
- emit_json(protected_call(client, "recover", params, mutation))
32
- return
33
- end
34
- attempt_id = require_option(options, :attempt, "reconcile --attempt ID [--receipt FILE]")
35
- receipt = options[:receipt].to_s.strip
36
-
37
- result = build_coordinator.reconcile(
38
- attempt_id: attempt_id,
39
- receipt_path: receipt.empty? ? nil : receipt
40
- )
41
-
42
- emit_json(result.projection)
43
- end
44
- end
45
- end
46
- end
47
- end
48
- end
49
- end
@@ -1,45 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "json"
4
- require_relative "base"
5
-
6
- module Ace
7
- module Assign
8
- module CLI
9
- module Commands
10
- module Attempt
11
- # Bind an immutable attempt to an assignment step/subtree.
12
- #
13
- # Identity is derived from the execution boundary; a repeated
14
- # identical start returns the active attempt, and a conflicting
15
- # binding fails without launching a second writer.
16
- class Start < Ace::Support::Cli::Command
17
- include Ace::Support::Cli::Base
18
- include Attempt::Base
19
-
20
- desc "Start a scoped attempt for an assignment step"
21
-
22
- option :assignment, desc: "Assignment ID"
23
- option :step, desc: "Step or subtree scope (e.g. 010 or 010.01)"
24
- option :project, desc: "Project ID the attempt executes in"
25
-
26
- def call(**options)
27
- usage = "start --assignment ID --step STEP --project ID"
28
- assignment = require_option(options, :assignment, usage)
29
- step = require_option(options, :step, usage)
30
- project = require_option(options, :project, usage)
31
-
32
- attempt = build_coordinator.start(
33
- assignment_id: assignment,
34
- step: step,
35
- project_id: project
36
- )
37
-
38
- emit_json(attempt.projection)
39
- end
40
- end
41
- end
42
- end
43
- end
44
- end
45
- end
@@ -1,54 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "json"
4
- require_relative "base"
5
-
6
- module Ace
7
- module Assign
8
- module CLI
9
- module Commands
10
- module Attempt
11
- # Show attempt state, binding facts, and evidence references.
12
- # JSON output carries only state, binding, references, and digests
13
- # — never credentials or receipt bytes.
14
- class Status < Ace::Support::Cli::Command
15
- include Ace::Support::Cli::Base
16
- include Attempt::Base
17
-
18
- desc "Show attempt status for an assignment"
19
-
20
- option :assignment, desc: "Assignment ID"
21
- option :format, desc: "Output format (json, text)", default: "json"
22
-
23
- def call(**options)
24
- assignment = require_option(options, :assignment, "status --assignment ID --format json")
25
- projection = build_coordinator.status(assignment)
26
-
27
- if options[:format] == "text"
28
- print_text(assignment, projection)
29
- else
30
- emit_json(projection || {"attempt" => nil})
31
- end
32
- end
33
-
34
- private
35
-
36
- def print_text(assignment, projection)
37
- return puts "No attempts recorded for #{assignment}" if projection.nil?
38
-
39
- puts "Attempt: #{projection['attempt_id']} #{projection['state']} (#{projection['scope']})"
40
- puts "Recovery: #{projection['recovery_mode']}"
41
- puts "Base head: #{projection['base_head']}"
42
- puts "Candidate head: #{projection['candidate_head'] || 'unpinned'}"
43
- puts "Evidence ref: #{projection['evidence_git_ref'] || 'local-only'}"
44
- puts "Journal commit: #{projection['journal_commit'] || 'none'}"
45
- return unless projection["unresolved_effects"].any?
46
-
47
- puts "Unresolved effects: #{projection['unresolved_effects'].join(', ')}"
48
- end
49
- end
50
- end
51
- end
52
- end
53
- end
54
- end
@@ -1,25 +0,0 @@
1
- # frozen_string_literal: true
2
- require_relative "../../../authority/prepared_task_context"
3
-
4
- module Ace
5
- module Assign
6
- module CLI
7
- module Commands
8
- module Authority
9
- class InboxContextPrincipal < Ace::Support::Cli::Command
10
- desc "Classify the actual caller through every retained protected owner"
11
-
12
- def call(**options)
13
- raise ArgumentError, "fixed inbox context options differ" unless options.empty?
14
- consumer = Ace::Assign::Authority::PreparedTaskContext.new(context: @protected_assignment_context)
15
- $stdout.write(consumer.inbox_principal())
16
- 0
17
- rescue ArgumentError, Ace::Runtime::Error, Ace::Assign::Error => error
18
- raise Ace::Support::Cli::Error, error.message
19
- end
20
- end
21
- end
22
- end
23
- end
24
- end
25
- end
@@ -1,28 +0,0 @@
1
- # frozen_string_literal: true
2
- require_relative "../../../authority/prepared_task_context"
3
-
4
- module Ace
5
- module Assign
6
- module CLI
7
- module Commands
8
- module Authority
9
- class InboxContextSelection < Ace::Support::Cli::Command
10
- desc "Read the fixed installed inbox context selection"
11
- option :project, required: true, desc: "Installed project ID"
12
- option :mapping, required: true, desc: "Installed mapping ID"
13
- option :inbox_context, required: true, desc: "Installed inbox context ID"
14
-
15
- def call(**options)
16
- raise ArgumentError, "fixed inbox context options differ" unless options.keys.sort == %i[inbox_context mapping project]
17
- consumer = Ace::Assign::Authority::PreparedTaskContext.new(context: @protected_assignment_context)
18
- $stdout.write(consumer.inbox_selection(**options))
19
- 0
20
- rescue ArgumentError, Ace::Runtime::Error, Ace::Assign::Error => error
21
- raise Ace::Support::Cli::Error, error.message
22
- end
23
- end
24
- end
25
- end
26
- end
27
- end
28
- end
@@ -1,97 +0,0 @@
1
- # frozen_string_literal: true
2
- require "json"
3
- require_relative "../../../authority/launch_driver"
4
- module Ace
5
- module Assign
6
- module CLI
7
- module Commands
8
- module Authority
9
- class Launch < Ace::Support::Cli::Command
10
- desc "Launch one mapped worker and retain its original foreground control channel"
11
- READY_FIELDS = %w[assignment_id attempt_id generation journal_commit mapping_id original_binding_digest type version].freeze
12
- READY_LIMIT = 16_384
13
- option :mapping, required: true, desc: "Installed launch mapping ID"
14
- option :assignment, desc: "Managed assignment ID"
15
- option :definition, desc: "Retained final prepared assignment definition JSON file"
16
- option :prepared_bundle, desc: "Retained original prepared input Git bundle"
17
- option :step, desc: "Assignment subtree scope"
18
- option :base_head, desc: "Exact base commit SHA"
19
- option :mutation, desc: "Stable invocation ID for safe replay"
20
- option :dry_run, type: :boolean, default: false, desc: "Verify installed boundary without mutation or creation"
21
- def call(**options)
22
- driver = build_driver(options.fetch(:mapping))
23
- result = if options[:dry_run]
24
- driver.preflight
25
- else
26
- %i[assignment definition prepared_bundle step base_head].each do |key|
27
- raise ArgumentError, "Missing --#{key.to_s.tr('_', '-')}" unless options[key].is_a?(String) && !options[key].empty?
28
- end
29
- definition = retained_input(options[:definition], 32_768).force_encoding(Encoding::UTF_8)
30
- raise ArgumentError, "assignment definition is not UTF-8" unless definition.valid_encoding?
31
- bundle = retained_input(options[:prepared_bundle], Ace::Assign::Authority::CandidateTransfer::MAX_BYTES)
32
- args = {prepared_bundle: bundle, assignment_id: options[:assignment], definition_bytes: definition,
33
- scope: options[:step], base_head: options[:base_head]}
34
- args[:mutation_id] = options[:mutation] if options[:mutation]
35
- driver.launch(**args)
36
- end
37
- if !options[:dry_run] && result["phase"] == "issued"
38
- retaining_control = true
39
- announced = false
40
- driver.serve_control!(state: result) do |ready|
41
- raise ArgumentError, "original launch readiness was already announced" if announced
42
- line = readiness_line(ready, result, options)
43
- $stdout.write(line)
44
- $stdout.flush
45
- announced = true
46
- end
47
- raise ArgumentError, "original control ended before authenticated readiness" unless announced
48
- else
49
- puts JSON.generate(result)
50
- end
51
- rescue ArgumentError, SystemCallError, Ace::Runtime::Error, Ace::Assign::Error => error
52
- raise Ace::Support::Cli::Error, error.message
53
- ensure
54
- # Local foreground-loop cancellation is not a stopped/settled proof.
55
- driver.request_control_cancel if retaining_control
56
- end
57
- private
58
- def retained_input(path, limit)
59
- File.open(path, File::RDONLY | File::NOFOLLOW | File::NONBLOCK) do |file|
60
- before = file.stat
61
- unless before.file? && before.size.between?(1, limit)
62
- raise ArgumentError, "retained launch input is not a bounded regular file"
63
- end
64
- bytes = (file.read(limit + 1) || "").b
65
- after = file.stat
66
- identity = ->(stat) { [stat.dev, stat.ino, stat.size, stat.mtime, stat.ctime] }
67
- unless bytes.bytesize == before.size && bytes.bytesize <= limit && identity.call(before) == identity.call(after)
68
- raise ArgumentError, "retained launch input changed while reading"
69
- end
70
- bytes
71
- end
72
- end
73
-
74
- def readiness_line(ready, result, options)
75
- unless ready.is_a?(Hash) && ready.keys.all? { |key| key.is_a?(String) } && ready.keys.sort == READY_FIELDS &&
76
- ready["version"].is_a?(Integer) && ready["version"] == 1 && ready["type"] == "launch_ready" &&
77
- ready.values_at("mapping_id", "assignment_id", "attempt_id") ==
78
- [options.fetch(:mapping), options.fetch(:assignment), result.fetch("attempt_id")] &&
79
- ready["generation"].is_a?(Integer) && ready["generation"].positive? &&
80
- ready["journal_commit"].is_a?(String) && ready["journal_commit"].match?(/\A(?:[0-9a-f]{40}|[0-9a-f]{64})\z/) &&
81
- ready["original_binding_digest"].is_a?(String) && ready["original_binding_digest"].match?(/\A[0-9a-f]{64}\z/)
82
- raise ArgumentError, "original launch readiness is malformed or mismatched"
83
- end
84
- line = JSON.generate(ready) + "\n"
85
- raise ArgumentError, "original launch readiness is oversized" if line.bytesize > READY_LIMIT
86
- line
87
- end
88
-
89
- def build_driver(mapping)
90
- Ace::Assign::Authority::LaunchDriver.new(mapping_id: mapping)
91
- end
92
- end
93
- end
94
- end
95
- end
96
- end
97
- end
@@ -1,31 +0,0 @@
1
- # frozen_string_literal: true
2
- require_relative "../../../authority/server"
3
- require_relative "../../../authority/router"
4
- require_relative "../../../authority/launch_lifecycle"
5
- module Ace
6
- module Assign
7
- module CLI
8
- module Commands
9
- module Authority
10
- class Serve < Ace::Support::Cli::Command
11
- desc "Serve the installed protected assignment authority"
12
- option :authority, required: true, desc: "Installed authority ID"
13
- def call(**options)
14
- deployment = Ace::Assign::Authority::Deployment.load
15
- history = Ace::Assign::Authority::DeploymentHistory.load
16
- launch = Ace::Assign::Authority::LaunchLifecycle.new(deployment: deployment, deployment_history: history)
17
- router = Ace::Assign::Authority::Router.new(launch: launch)
18
- server = Ace::Assign::Authority::Server.new(authority_id: options.fetch(:authority), deployment: deployment, lifecycle: router)
19
- signals = %w[INT TERM].to_h { |signal| [signal, Signal.trap(signal) { server.request_stop }] }
20
- server.serve
21
- rescue ArgumentError, Ace::Runtime::Error, Ace::Assign::Error => error
22
- raise Ace::Support::Cli::Error, error.message
23
- ensure
24
- signals&.each { |signal, handler| Signal.trap(signal, handler) }
25
- end
26
- end
27
- end
28
- end
29
- end
30
- end
31
- end
@@ -1,26 +0,0 @@
1
- # frozen_string_literal: true
2
- require "json"
3
- require_relative "../../../authority/client"
4
- module Ace
5
- module Assign
6
- module CLI
7
- module Commands
8
- module Authority
9
- class Status < Ace::Support::Cli::Command
10
- desc "Inspect canonical protected launch ownership"
11
- option :mapping, required: true, desc: "Installed launch mapping ID"
12
- option :assignment, required: true, desc: "Assignment ID"
13
- option :attempt, required: true, desc: "Attempt ID"
14
- def call(**options)
15
- reply = Ace::Assign::Authority::Client.new(mapping_id: options.fetch(:mapping)).call("attempt_status",
16
- {"assignment_id" => options.fetch(:assignment), "attempt_id" => options.fetch(:attempt), "result_candidate_generation" => nil})
17
- puts JSON.generate(reply.data)
18
- rescue ArgumentError, Ace::Runtime::Error, Ace::Assign::Error => error
19
- raise Ace::Support::Cli::Error, error.message
20
- end
21
- end
22
- end
23
- end
24
- end
25
- end
26
- end
@@ -1,31 +0,0 @@
1
- # frozen_string_literal: true
2
- require_relative "../../../authority/prepared_task_context"
3
-
4
- module Ace
5
- module Assign
6
- module CLI
7
- module Commands
8
- module Authority
9
- class TaskContext < Ace::Support::Cli::Command
10
- desc "Return the captured original task context through the fixed selected entry"
11
- option :mapping, required: true, desc: "Installed original mapping ID"
12
- option :assignment, required: true, desc: "Original assignment ID@SCOPE"
13
- option :attempt, required: true, desc: "Original protected attempt ID"
14
- option :task, required: true, desc: "Captured canonical task ID"
15
-
16
- def call(**options)
17
- unless options.keys.sort == %i[assignment attempt mapping task]
18
- raise ArgumentError, "fixed task-context accepts only its four selectors"
19
- end
20
- consumer = Ace::Assign::Authority::PreparedTaskContext.new(context: @protected_assignment_context)
21
- $stdout.write(consumer.call(**options))
22
- 0
23
- rescue ArgumentError, Ace::Runtime::Error, Ace::Assign::Error => error
24
- raise Ace::Support::Cli::Error, error.message
25
- end
26
- end
27
- end
28
- end
29
- end
30
- end
31
- end
@@ -1,25 +0,0 @@
1
- # frozen_string_literal: true
2
- require_relative "../../../authority/prepared_task_context"
3
-
4
- module Ace
5
- module Assign
6
- module CLI
7
- module Commands
8
- module Authority
9
- class TaskContextPrincipal < Ace::Support::Cli::Command
10
- desc "Classify this actual caller through the installed and retained protected owners"
11
-
12
- def call(**options)
13
- raise ArgumentError, "fixed task-context-principal accepts no options" unless options.empty?
14
- consumer = Ace::Assign::Authority::PreparedTaskContext.new(context: @protected_assignment_context)
15
- $stdout.write(consumer.principal)
16
- 0
17
- rescue ArgumentError, Ace::Runtime::Error, Ace::Assign::Error => error
18
- raise Ace::Support::Cli::Error, error.message
19
- end
20
- end
21
- end
22
- end
23
- end
24
- end
25
- end
@@ -1,30 +0,0 @@
1
- # frozen_string_literal: true
2
- require_relative "../../../authority/prepared_task_context"
3
-
4
- module Ace
5
- module Assign
6
- module CLI
7
- module Commands
8
- module Authority
9
- class TaskContextSelection < Ace::Support::Cli::Command
10
- desc "Return the authenticated original task-context entry without captured text"
11
- option :mapping, required: true, desc: "Installed original mapping ID"
12
- option :assignment, required: true, desc: "Original assignment ID@SCOPE"
13
- option :attempt, required: true, desc: "Original protected attempt ID"
14
-
15
- def call(**options)
16
- unless options.keys.sort == %i[assignment attempt mapping]
17
- raise ArgumentError, "fixed task-context-selection accepts only its three selectors"
18
- end
19
- consumer = Ace::Assign::Authority::PreparedTaskContext.new(context: @protected_assignment_context)
20
- $stdout.write(consumer.selection(**options))
21
- 0
22
- rescue ArgumentError, Ace::Runtime::Error, Ace::Assign::Error => error
23
- raise Ace::Support::Cli::Error, error.message
24
- end
25
- end
26
- end
27
- end
28
- end
29
- end
30
- end
@@ -1,29 +0,0 @@
1
- # frozen_string_literal: true
2
- require "json"
3
- require_relative "../../../authority/launch_driver"
4
- module Ace
5
- module Assign
6
- module CLI
7
- module Commands
8
- module Authority
9
- class Terminate < Ace::Support::Cli::Command
10
- desc "Close the original gated native child and request proven abort"
11
- option :mapping, required: true, desc: "Installed launch mapping ID"
12
- option :assignment, required: true, desc: "Assignment ID"
13
- option :attempt, required: true, desc: "Attempt ID"
14
- def call(**options)
15
- client = Ace::Assign::Authority::Client.new(mapping_id: options.fetch(:mapping))
16
- state = client.call("inspect_launch", {"assignment_id" => options.fetch(:assignment), "attempt_id" => options.fetch(:attempt)}).data
17
- binding = state.fetch("process_binding") { raise ArgumentError, "no positively recorded original child; supervisor inspection required" }
18
- result = Ace::Assign::Authority::LaunchDriver.new(mapping_id: options.fetch(:mapping)).terminate(
19
- state: state, binding: binding, evidence: "protected exact-child termination requested")
20
- puts JSON.generate(result)
21
- rescue ArgumentError, Ace::Runtime::Error, Ace::Assign::Error => error
22
- raise Ace::Support::Cli::Error, error.message
23
- end
24
- end
25
- end
26
- end
27
- end
28
- end
29
- end
@@ -1,23 +0,0 @@
1
- # frozen_string_literal: true
2
- require_relative "../../../authority/prepared_worker"
3
-
4
- module Ace
5
- module Assign
6
- module CLI
7
- module Commands
8
- module Authority
9
- class Worker < Ace::Support::Cli::Command
10
- desc "Consume the original authenticated prepared subtree as its fixed worker"
11
-
12
- def call(**options)
13
- raise ArgumentError, "fixed worker accepts no options" unless options.empty?
14
- Ace::Assign::Authority::PreparedWorker.new.run
15
- rescue ArgumentError, Ace::Runtime::Error, Ace::Assign::Error => error
16
- raise Ace::Support::Cli::Error, error.message
17
- end
18
- end
19
- end
20
- end
21
- end
22
- end
23
- end
@@ -1,55 +0,0 @@
1
- # frozen_string_literal: true
2
- require_relative "protected_submission"
3
-
4
- module Ace
5
- module Assign
6
- module CLI
7
- module Commands
8
- class CampaignExportResult < Ace::Support::Cli::Command
9
- include Ace::Support::Cli::Base
10
- include ProtectedSubmission
11
- desc "Download a verified accepted campaign result through its original authority"
12
- option :mapping, desc: "Original installed parent mapping"
13
- option :assignment, desc: "Original parent assignment"
14
- option :attempt, desc: "Original parent attempt"
15
- option :head, desc: "Exact parent candidate head"
16
- option :candidate_generation, desc: "Exact parent candidate counter"
17
- option :output, desc: "Result byte file (created once, exact retries allowed)"
18
-
19
- def call(**options)
20
- usage = "campaign-export-result with original parent selectors and --output FILE"
21
- context = protected_context(options)
22
- raise AttemptErrors::EvidenceUnavailable, "Campaign export requires installed authority" unless context
23
- params = {"assignment_id" => require_option(options, :assignment, usage),
24
- "attempt_id" => require_option(options, :attempt, usage), "head" => require_option(options, :head, usage),
25
- "candidate_generation" => integer_option(options, :candidate_generation, usage, positive: true)}
26
- raise Ace::Support::Cli::Error, "Campaign head must be an exact SHA-1" unless params["head"].match?(/\A[0-9a-f]{40}\z/)
27
- context.verify_attempt_hints!(assignment_id: params.fetch("assignment_id"), attempt_id: params.fetch("attempt_id"))
28
- path = require_option(options, :output, usage)
29
- reply = context.client(options: options).call("campaign_export_result", params, download: true, purpose: :artifacts, timeout: 30)
30
- bytes = reply.parts&.first
31
- unless reply.parts&.size == 1 && bytes.is_a?(String) && bytes.bytesize <= 64 * 1024 &&
32
- reply.data.values_at("head", "candidate_generation", "bytes", "sha256") ==
33
- [params.fetch("head"), params.fetch("candidate_generation"), bytes.bytesize, Digest::SHA256.hexdigest(bytes)]
34
- raise AttemptErrors::EvidenceUnavailable, "Campaign result download differs"
35
- end
36
- begin
37
- File.open(path, File::WRONLY | File::CREAT | File::EXCL | File::NOFOLLOW, 0o600) do |file|
38
- file.write(bytes)
39
- file.flush
40
- file.fsync
41
- end
42
- rescue Errno::EEXIST
43
- raise Ace::Support::Cli::Error, "Existing campaign result file differs" unless input_bytes(path, limit: 64 * 1024) == bytes
44
- end
45
- emit_json(reply.data.except("transfer").merge("path" => path))
46
- rescue SecurityError, Ace::Runtime::RuntimeUnavailableError
47
- protected_transport_unavailable!
48
- rescue SystemCallError, IOError
49
- raise Ace::Support::Cli::Error, "Campaign result file or transport is unavailable"
50
- end
51
- end
52
- end
53
- end
54
- end
55
- end