harnex 0.7.13 → 0.7.14

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.
@@ -31,6 +31,9 @@ module Harnex
31
31
  BUDGET_META_FIELDS = %w[read_budget_lines output_ceiling_lines].freeze
32
32
  QUEUE_FIELDS = %w[project_id queue_id entry_id entry_title issue plan phase tier intent].freeze
33
33
  AGENT_FIELDS = %w[cli provider model_requested model_effective reasoning_effort service_tier adapter_transport].freeze
34
+ ORCHESTRATION_FIELDS = %w[
35
+ run_id generation_id role project_id queue_id session_id rotation_reason
36
+ ].freeze
34
37
  RELIABILITY_FIELDS = %w[
35
38
  adapter_close real_disconnections stream_interruptions stalls force_resumes compactions recovered
36
39
  ].freeze
@@ -70,7 +73,7 @@ module Harnex
70
73
  return unless item.is_a?(Hash)
71
74
 
72
75
  case item["type"]
73
- when "mcpToolCall", "dynamicToolCall"
76
+ when "mcpToolCall", "dynamicToolCall", "fileChange", "webSearch"
74
77
  @counts[:tool_calls] += 1
75
78
  when "commandExecution"
76
79
  @counts[:commands_executed] += 1
@@ -84,9 +87,9 @@ module Harnex
84
87
 
85
88
  attr_reader :repo_root, :launch_cwd, :child_cwd, :host, :port, :session_id, :token, :command, :pid, :id, :adapter, :watch,
86
89
  :inbox, :description, :meta, :summary_out, :artifact_report_path, :output_log_path, :events_log_path,
87
- :started_at, :ended_at, :exit_code, :term_signal
90
+ :started_at, :ended_at, :exit_code, :term_signal, :require_artifact_report
88
91
 
89
- def initialize(adapter:, command:, repo_root:, host:, port: nil, id: DEFAULT_ID, watch: nil, description: nil, meta: nil, summary_out: nil, artifact_report_path: nil, inbox_ttl: Inbox::DEFAULT_TTL, auto_stop: false, launch_cwd: nil, child_cwd: nil)
92
+ def initialize(adapter:, command:, repo_root:, host:, port: nil, id: DEFAULT_ID, watch: nil, description: nil, meta: nil, summary_out: nil, artifact_report_path: nil, require_artifact_report: false, inbox_ttl: Inbox::DEFAULT_TTL, auto_stop: false, launch_cwd: nil, child_cwd: nil)
90
93
  @adapter = adapter
91
94
  @command = command
92
95
  @repo_root = repo_root
@@ -103,6 +106,9 @@ module Harnex
103
106
  @artifact_report_path = artifact_report_path.to_s.strip
104
107
  @artifact_report_path = nil if @artifact_report_path.empty?
105
108
  @artifact_report_path = File.expand_path(@artifact_report_path, repo_root) if @artifact_report_path
109
+ @require_artifact_report = !!require_artifact_report
110
+ raise ArgumentError, "require_artifact_report requires artifact_report_path" if @require_artifact_report && !@artifact_report_path
111
+ @artifact_report_start_fingerprint = Harnex::ArtifactReport.fingerprint(@artifact_report_path) if @artifact_report_path
106
112
  @registry_path = Harnex.registry_path(repo_root, @id)
107
113
  @output_log_path = Harnex.output_log_path(repo_root, @id)
108
114
  @events_log_path = Harnex.events_log_path(repo_root, @id)
@@ -136,6 +142,9 @@ module Harnex
136
142
  @last_completed_at = nil
137
143
  @last_failed_at = nil
138
144
  @last_failed_status = nil
145
+ @completion_outcome_class = nil
146
+ @completion_report_status = nil
147
+ @completion_diagnostics = []
139
148
  @pi_streamed_text_by_message = {}
140
149
  @auto_stop = !!auto_stop
141
150
  @auto_stop_fired = false
@@ -208,6 +217,8 @@ module Harnex
208
217
  @exit_code = status.exited? ? status.exitstatus : 128 + status.termsig
209
218
  @ended_at = Time.now
210
219
 
220
+ enforce_required_artifact_report!
221
+ normalize_work_acceptance_exit_code!
211
222
  normalize_auto_stop_exit_code!
212
223
  drain_auto_stop_threads
213
224
  output_thread.join(1)
@@ -268,6 +279,8 @@ module Harnex
268
279
  payload[:task_failed] = task_failed
269
280
  payload[:done] = Harnex.work_done_for("running", task_complete: task_complete)
270
281
  payload[:work_state] = work_state
282
+ payload[:outcome_class] = @completion_outcome_class
283
+ payload[:artifact_report_status] = @completion_report_status
271
284
  payload[:last_error] = @last_error
272
285
  payload[:model] = summary_model
273
286
  payload[:effort] = meta_hash["effort"]
@@ -482,6 +495,8 @@ module Harnex
482
495
  end
483
496
  @ended_at = Time.now
484
497
 
498
+ enforce_required_artifact_report!
499
+ normalize_work_acceptance_exit_code!
485
500
  normalize_auto_stop_exit_code!
486
501
  drain_auto_stop_threads
487
502
  finalize_session!
@@ -540,8 +555,7 @@ module Harnex
540
555
  payload[:status] = status if status
541
556
  payload[:tokenUsage] = params["tokenUsage"] if params["tokenUsage"].is_a?(Hash)
542
557
  if successful_turn_status?(status)
543
- @last_completed_at = Time.now
544
- emit_event("task_complete", **payload)
558
+ record_successful_completion(payload)
545
559
  else
546
560
  mark_task_failed(
547
561
  turn_id: turn_id,
@@ -600,15 +614,170 @@ module Harnex
600
614
  SUCCESSFUL_TURN_STATUSES.include?(text)
601
615
  end
602
616
 
603
- def mark_task_failed(turn_id: nil, status: nil, error: nil, codex_error_info: nil)
617
+ def record_successful_completion(payload)
618
+ assessment = completion_gate_required? ? assess_completion_proof : { accepted: true }
619
+ unless assessment[:accepted]
620
+ mark_task_failed(
621
+ turn_id: payload[:turnId],
622
+ status: assessment.fetch(:outcome_class),
623
+ error: completion_failure_message(assessment.fetch(:outcome_class)),
624
+ outcome_class: assessment.fetch(:outcome_class),
625
+ artifact_report_status: assessment[:report_status],
626
+ diagnostics: assessment[:diagnostics]
627
+ )
628
+ return false
629
+ end
630
+
631
+ @last_failed_at = nil
632
+ @last_failed_status = nil
633
+ @last_error = nil
634
+ @last_completed_at = Time.now
635
+ if assessment[:outcome_class]
636
+ @completion_outcome_class = assessment[:outcome_class]
637
+ @completion_report_status = assessment[:report_status]
638
+ @completion_diagnostics = []
639
+ end
640
+
641
+ event_payload = payload.dup
642
+ event_payload[:outcome_class] = @completion_outcome_class if @completion_outcome_class
643
+ event_payload[:artifact_report_status] = @completion_report_status if @completion_report_status
644
+ emit_event("task_complete", **event_payload)
645
+ true
646
+ end
647
+
648
+ def completion_gate_required?
649
+ return true if require_artifact_report
650
+ return false unless adapter.transport == :stdio_jsonrpc
651
+
652
+ @auto_stop || (adapter.respond_to?(:initial_prompt) && !adapter.initial_prompt.to_s.empty?)
653
+ end
654
+
655
+ def assess_completion_proof
656
+ report_result = artifact_report_path ? Harnex::ArtifactReport.validate(artifact_report_path, final: true) : nil
657
+ report_fresh = report_result && report_result.status != "missing" && artifact_report_fresh?
658
+ report_stale = report_result && Harnex::ArtifactReport.accepted_final?(report_result) && !report_fresh
659
+ report_status = report_stale ? "stale" : report_result&.status
660
+ report_diagnostics = if report_stale
661
+ [artifact_report_stale_diagnostic]
662
+ else
663
+ report_result&.diagnostics || []
664
+ end
665
+
666
+ if report_result
667
+ if report_fresh && Harnex::ArtifactReport.accepted_final?(report_result)
668
+ return {
669
+ accepted: true,
670
+ outcome_class: "completed_with_proof",
671
+ report_status: "accepted",
672
+ diagnostics: []
673
+ }
674
+ end
675
+
676
+ report_outcome = Harnex::ArtifactReport.outcome_status(report_result)
677
+ if report_fresh && report_outcome == "rejected"
678
+ return {
679
+ accepted: false,
680
+ outcome_class: "report_rejected",
681
+ report_status: "rejected",
682
+ diagnostics: report_result.diagnostics
683
+ }
684
+ end
685
+
686
+ if require_artifact_report
687
+ outcome_class = report_result.status == "missing" ? "report_missing" : "report_invalid"
688
+ return {
689
+ accepted: false,
690
+ outcome_class: outcome_class,
691
+ report_status: report_status,
692
+ diagnostics: report_diagnostics
693
+ }
694
+ end
695
+ elsif require_artifact_report
696
+ return {
697
+ accepted: false,
698
+ outcome_class: "report_missing",
699
+ report_status: "missing",
700
+ diagnostics: []
701
+ }
702
+ end
703
+
704
+ if structured_activity_observed? || git_activity_observed?
705
+ {
706
+ accepted: true,
707
+ outcome_class: "completed_with_activity",
708
+ report_status: report_status,
709
+ diagnostics: []
710
+ }
711
+ else
712
+ {
713
+ accepted: false,
714
+ outcome_class: "completed_no_activity",
715
+ report_status: report_status,
716
+ diagnostics: report_diagnostics
717
+ }
718
+ end
719
+ end
720
+
721
+ def artifact_report_fresh?
722
+ current = Harnex::ArtifactReport.fingerprint(artifact_report_path)
723
+ return false unless current
724
+ return true unless @artifact_report_start_fingerprint
725
+
726
+ current != @artifact_report_start_fingerprint
727
+ end
728
+
729
+ def artifact_report_stale_diagnostic
730
+ {
731
+ "code" => "report_stale",
732
+ "path" => "$",
733
+ "message" => "artifact report was not created or updated during this session"
734
+ }
735
+ end
736
+
737
+ def structured_activity_observed?
738
+ counters = @event_counters.snapshot
739
+ counters[:commands_executed].to_i.positive? || counters[:tool_calls].to_i.positive?
740
+ end
741
+
742
+ def git_activity_observed?
743
+ return false if @git_start[:sha].to_s.empty?
744
+
745
+ snapshot = Harnex.git_capture_end(repo_root, @git_start[:sha])
746
+ snapshot[:commits].to_i.positive? || Array(snapshot[:changed_paths]).any? ||
747
+ (!snapshot[:sha].to_s.empty? && snapshot[:sha].to_s != @git_start[:sha].to_s)
748
+ end
749
+
750
+ def completion_failure_message(outcome_class)
751
+ case outcome_class
752
+ when "completed_no_activity"
753
+ "turn completed without command/tool execution, Git delta, or accepted artifact report"
754
+ when "report_missing"
755
+ "required artifact report is missing"
756
+ when "report_rejected"
757
+ "artifact report rejected work completion"
758
+ when "report_invalid"
759
+ "required artifact report is not valid final proof"
760
+ else
761
+ "work completion was not accepted"
762
+ end
763
+ end
764
+
765
+ def mark_task_failed(turn_id: nil, status: nil, error: nil, codex_error_info: nil, outcome_class: nil, artifact_report_status: nil, diagnostics: nil)
766
+ @last_completed_at = nil if outcome_class
604
767
  @last_failed_at = Time.now
605
768
  @last_failed_status = status.to_s.empty? ? "failed" : status.to_s
606
769
  @last_error = error.to_s unless error.to_s.empty?
770
+ @completion_outcome_class = outcome_class if outcome_class
771
+ @completion_report_status = artifact_report_status if artifact_report_status
772
+ @completion_diagnostics = Array(diagnostics).first(Harnex::ArtifactReport::MAX_DIAGNOSTICS) if diagnostics
607
773
 
608
774
  payload = { status: @last_failed_status }
609
775
  payload[:turnId] = turn_id if turn_id
610
776
  payload[:message] = error unless error.to_s.empty?
611
777
  payload[:codex_error_info] = codex_error_info if codex_error_info
778
+ payload[:outcome_class] = outcome_class if outcome_class
779
+ payload[:artifact_report_status] = artifact_report_status if artifact_report_status
780
+ payload[:diagnostics] = @completion_diagnostics unless @completion_diagnostics.empty?
612
781
  emit_event("task_failed", **payload)
613
782
  end
614
783
 
@@ -655,9 +824,8 @@ module Harnex
655
824
  @state_machine.force_busy!
656
825
  emit_event("turn_started") if event_type == "turn_start"
657
826
  when "agent_end"
658
- @last_completed_at = Time.now
659
827
  @state_machine.force_prompt!
660
- emit_event("task_complete")
828
+ record_successful_completion({})
661
829
  adapter.request_session_stats_async if adapter.respond_to?(:request_session_stats_async)
662
830
  schedule_auto_stop("task_complete", interrupt: false)
663
831
  when "message_start"
@@ -836,6 +1004,7 @@ module Harnex
836
1004
  env["HARNEX_ARTIFACT_REPORT_PATH"] = artifact_report_path
837
1005
  env["HARNEX_VALIDATION_REPORT_PATH"] = artifact_report_path
838
1006
  env["HARNEX_ARTIFACT_REPORT_SCHEMA"] = Harnex::ArtifactReport::SCHEMA
1007
+ env["HARNEX_ARTIFACT_REPORT_REQUIRED"] = "1" if require_artifact_report
839
1008
  end
840
1009
  env["HARNEX_SPAWNER_PANE"] = ENV["TMUX_PANE"] if ENV["TMUX_PANE"]
841
1010
  env
@@ -920,6 +1089,8 @@ module Harnex
920
1089
  task_failed: task_failed,
921
1090
  done: Harnex.work_done_for(state, task_complete: task_complete),
922
1091
  work_state: Harnex.work_state_for(state, task_complete: task_complete),
1092
+ outcome_class: @completion_outcome_class,
1093
+ artifact_report_status: @completion_report_status,
923
1094
  started_at: @started_at.iso8601,
924
1095
  exited_at: Time.now.iso8601,
925
1096
  injected_count: @injected_count
@@ -1143,7 +1314,10 @@ module Harnex
1143
1314
  seen_busy = @auto_stop_mutex.synchronize do
1144
1315
  @auto_stop_seen_busy ||= old_state == :busy || new_state == :busy
1145
1316
  end
1146
- schedule_auto_stop("prompt_after_busy") if seen_busy && new_state == :prompt
1317
+ return unless seen_busy && new_state == :prompt
1318
+
1319
+ record_successful_completion({}) if require_artifact_report
1320
+ schedule_auto_stop("prompt_after_busy")
1147
1321
  end
1148
1322
 
1149
1323
  def schedule_auto_stop(reason, turn_id: nil, interrupt: true)
@@ -1205,6 +1379,55 @@ module Harnex
1205
1379
  AUTOSTOP_TEARDOWN_GRACE_SECONDS_DEFAULT
1206
1380
  end
1207
1381
 
1382
+ def enforce_required_artifact_report!
1383
+ return unless require_artifact_report
1384
+ return if task_failed? && %w[report_missing report_invalid report_rejected].include?(@completion_outcome_class)
1385
+
1386
+ result = Harnex::ArtifactReport.validate(artifact_report_path, final: true)
1387
+ report_fresh = result.status != "missing" && artifact_report_fresh?
1388
+ report_accepted = Harnex::ArtifactReport.accepted_final?(result)
1389
+ report_stale = report_accepted && !report_fresh
1390
+ if report_fresh && report_accepted
1391
+ @completion_outcome_class = "completed_with_proof"
1392
+ @completion_report_status = "accepted"
1393
+ @completion_diagnostics = []
1394
+ return
1395
+ end
1396
+
1397
+ report_outcome = Harnex::ArtifactReport.outcome_status(result)
1398
+ outcome_class = if report_fresh && report_outcome == "rejected"
1399
+ "report_rejected"
1400
+ elsif result.status == "missing"
1401
+ "report_missing"
1402
+ else
1403
+ "report_invalid"
1404
+ end
1405
+ report_status = if report_stale
1406
+ "stale"
1407
+ elsif report_fresh && report_outcome == "rejected"
1408
+ "rejected"
1409
+ else
1410
+ result.status
1411
+ end
1412
+ diagnostics = report_stale ? [artifact_report_stale_diagnostic] : result.diagnostics
1413
+ mark_task_failed(
1414
+ status: outcome_class,
1415
+ error: completion_failure_message(outcome_class),
1416
+ outcome_class: outcome_class,
1417
+ artifact_report_status: report_status,
1418
+ diagnostics: diagnostics
1419
+ )
1420
+ @exit_code = 1 if @exit_code.nil? || @exit_code.zero? || @term_signal
1421
+ @term_signal = nil if @exit_code == 1
1422
+ end
1423
+
1424
+ def normalize_work_acceptance_exit_code!
1425
+ return unless task_failed? && @completion_outcome_class
1426
+
1427
+ @exit_code = 1 if @exit_code.nil? || @exit_code.zero? || @term_signal
1428
+ @term_signal = nil if @exit_code == 1
1429
+ end
1430
+
1208
1431
  def normalize_auto_stop_exit_code!
1209
1432
  return unless @auto_stop
1210
1433
  return unless @auto_stop_fired
@@ -1223,9 +1446,11 @@ module Harnex
1223
1446
 
1224
1447
  def classify_exit
1225
1448
  return "timeout" if @exit_code == 124
1449
+ return "failure" if task_failed? && @completion_outcome_class
1226
1450
  return "boot_failure" if boot_failure_exit?
1227
1451
  return "failure" if task_failed?
1228
1452
  return "success" if @exit_code == 0 && task_complete?
1453
+ return "success" if @exit_code == 0 && @completion_outcome_class == "completed_with_proof"
1229
1454
  return "success" if @exit_code == 0 && session_summary_present?
1230
1455
  return "failure" unless @exit_code == 0
1231
1456
 
@@ -1262,6 +1487,8 @@ module Harnex
1262
1487
  }
1263
1488
  queue = build_summary_queue
1264
1489
  record[:queue] = queue if queue
1490
+ orchestration = build_summary_orchestration
1491
+ record[:orchestration] = orchestration if orchestration
1265
1492
  record.merge!(artifact_payload.reject { |key, _value| key == "outcome" }) if artifact_payload
1266
1493
  record
1267
1494
  end
@@ -1306,6 +1533,14 @@ module Harnex
1306
1533
  queue
1307
1534
  end
1308
1535
 
1536
+ def build_summary_orchestration
1537
+ orchestration = Orchestration.normalize_metadata(meta_hash)
1538
+ return nil unless orchestration
1539
+
1540
+ orchestration["session_id"] ||= summary_agent_session_id || session_id
1541
+ orchestration
1542
+ end
1543
+
1309
1544
  def build_summary_agent
1310
1545
  {
1311
1546
  "cli" => adapter.key,
@@ -1425,14 +1660,25 @@ module Harnex
1425
1660
 
1426
1661
  def build_summary_outcome(artifact_payload)
1427
1662
  sidecar_outcome = artifact_payload&.dig("outcome") || {}
1428
- status = sidecar_outcome["status"]
1429
- status = "no_change" if status.nil? && @git_end.key?(:changed_paths) && @git_end[:changed_paths].empty?
1663
+ outcome_class, report_status = summary_proof_classification
1664
+ proof_failure = %w[completed_no_activity report_missing report_invalid task_failed].include?(outcome_class)
1665
+ status = proof_failure ? nil : sidecar_outcome["status"]
1666
+ status = "no_change" if status.nil? && !proof_failure && @git_end.key?(:changed_paths) && @git_end[:changed_paths].empty?
1430
1667
  status ||= "unknown"
1431
- status = "unknown" unless %w[accepted rejected no_change unknown].include?(status)
1668
+ status = "unknown" unless Harnex::ArtifactReport::OUTCOME_STATUSES.include?(status)
1669
+ source = if proof_failure
1670
+ "harnex_completion_gate"
1671
+ elsif sidecar_outcome["status"]
1672
+ "artifact_report"
1673
+ else
1674
+ "harnex_git_observation"
1675
+ end
1432
1676
 
1433
1677
  {
1434
1678
  "status" => status,
1435
- "source" => sidecar_outcome["status"] ? "artifact_report" : "harnex_git_observation",
1679
+ "class" => outcome_class,
1680
+ "source" => source,
1681
+ "report_status" => report_status,
1436
1682
  "commit_sha" => sidecar_outcome["commit_sha"] || summary_commit_sha,
1437
1683
  "changed_paths" => @git_end.key?(:changed_paths) ? @git_end[:changed_paths] : nil,
1438
1684
  "loc_added" => @git_end[:loc_added],
@@ -1443,6 +1689,25 @@ module Harnex
1443
1689
  }
1444
1690
  end
1445
1691
 
1692
+ def summary_proof_classification
1693
+ return [@completion_outcome_class, @completion_report_status] if @completion_outcome_class
1694
+ return ["task_failed", @completion_report_status] if task_failed?
1695
+
1696
+ if artifact_report_path
1697
+ result = Harnex::ArtifactReport.validate(artifact_report_path, final: true)
1698
+ report_fresh = result.status != "missing" && artifact_report_fresh?
1699
+ report_accepted = Harnex::ArtifactReport.accepted_final?(result)
1700
+ return ["completed_with_proof", "accepted"] if report_fresh && report_accepted
1701
+ return ["report_rejected", "rejected"] if report_fresh && Harnex::ArtifactReport.outcome_status(result) == "rejected"
1702
+ return ["unknown", "stale"] if report_accepted && !report_fresh
1703
+ return ["unknown", result.status]
1704
+ end
1705
+
1706
+ return ["completed_with_activity", @completion_report_status] if task_complete? && structured_activity_observed?
1707
+
1708
+ ["unknown", @completion_report_status]
1709
+ end
1710
+
1446
1711
  def build_summary_attempt
1447
1712
  {
1448
1713
  "run_id" => id,
@@ -48,6 +48,8 @@ module Harnex
48
48
  "task_failed" => false,
49
49
  "done" => false,
50
50
  "work_state" => "unknown",
51
+ "outcome_class" => nil,
52
+ "artifact_report_status" => nil,
51
53
  "exit" => nil,
52
54
  "exit_code" => nil,
53
55
  "summary_out" => nil,
@@ -130,6 +132,7 @@ module Harnex
130
132
  def build_from_summary(record, summary_path, fallback_repo_root)
131
133
  meta = record["meta"] || {}
132
134
  actual = record["actual"] || {}
135
+ outcome = record["outcome"] || {}
133
136
  state = classify_summary_state(actual)
134
137
  task_complete = !!actual["task_complete"]
135
138
  task_failed = state == "failed" && !task_complete
@@ -144,6 +147,8 @@ module Harnex
144
147
  "task_failed" => task_failed,
145
148
  "done" => Harnex.work_done_for(state, task_complete: task_complete),
146
149
  "work_state" => Harnex.work_state_for(state, task_complete: task_complete),
150
+ "outcome_class" => blank_to_nil(outcome["class"]),
151
+ "artifact_report_status" => blank_to_nil(outcome["report_status"]),
147
152
  "exit" => blank_to_nil(actual["exit"]),
148
153
  "exit_code" => actual["exit_code"],
149
154
  "summary_out" => summary_path,
@@ -188,6 +193,8 @@ module Harnex
188
193
  "task_failed" => task_failed,
189
194
  "done" => Harnex.work_done_for(state, task_complete: task_complete),
190
195
  "work_state" => Harnex.work_state_for(state, task_complete: task_complete),
196
+ "outcome_class" => nil,
197
+ "artifact_report_status" => nil,
191
198
  "exit" => history_exit(status),
192
199
  "exit_code" => nil,
193
200
  "summary_out" => blank_to_nil(record["summary_out_path"]),
@@ -1,4 +1,4 @@
1
1
  module Harnex
2
- VERSION = "0.7.13"
2
+ VERSION = "0.7.14"
3
3
  RELEASE_DATE = "2026-07-15"
4
4
  end
data/lib/harnex.rb CHANGED
@@ -8,6 +8,7 @@ require_relative "harnex/dispatch_history"
8
8
  require_relative "harnex/terminal_status"
9
9
  require_relative "harnex/artifact_report"
10
10
  require_relative "harnex/context_telemetry"
11
+ require_relative "harnex/orchestration"
11
12
  require_relative "harnex/watcher"
12
13
  require_relative "harnex/adapters"
13
14
  require_relative "harnex/runtime/session_state"
@@ -31,4 +32,6 @@ require_relative "harnex/commands/recipes"
31
32
  require_relative "harnex/commands/guide"
32
33
  require_relative "harnex/commands/agents_guide"
33
34
  require_relative "harnex/commands/doctor"
35
+ require_relative "harnex/commands/orchestration"
36
+ require_relative "harnex/commands/artifact_report"
34
37
  require_relative "harnex/cli"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: harnex
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.13
4
+ version: 0.7.14
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jikku Jose
@@ -44,11 +44,13 @@ files:
44
44
  - lib/harnex/cli.rb
45
45
  - lib/harnex/codex/app_server/client.rb
46
46
  - lib/harnex/commands/agents_guide.rb
47
+ - lib/harnex/commands/artifact_report.rb
47
48
  - lib/harnex/commands/doctor.rb
48
49
  - lib/harnex/commands/events.rb
49
50
  - lib/harnex/commands/guide.rb
50
51
  - lib/harnex/commands/history.rb
51
52
  - lib/harnex/commands/logs.rb
53
+ - lib/harnex/commands/orchestration.rb
52
54
  - lib/harnex/commands/pane.rb
53
55
  - lib/harnex/commands/recipes.rb
54
56
  - lib/harnex/commands/run.rb
@@ -61,6 +63,7 @@ files:
61
63
  - lib/harnex/context_telemetry.rb
62
64
  - lib/harnex/core.rb
63
65
  - lib/harnex/dispatch_history.rb
66
+ - lib/harnex/orchestration.rb
64
67
  - lib/harnex/runtime/api_server.rb
65
68
  - lib/harnex/runtime/file_change_hook.rb
66
69
  - lib/harnex/runtime/inbox.rb