carson 4.3.0 → 4.3.2

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.
data/lib/cli.rb CHANGED
@@ -5,7 +5,7 @@ require "optparse"
5
5
  module Carson
6
6
  class CLI
7
7
  PORTFOLIO_COMMANDS = %w[onboard offboard list refresh version].freeze
8
- REPO_COMMANDS = %w[deliver receive sync status audit prune housekeep worktree abandon recover review template setup checkin checkout].freeze
8
+ REPO_COMMANDS = %w[deliver receive sync status prune housekeep worktree abandon recover review template setup checkin checkout].freeze
9
9
  ALL_COMMANDS = ( PORTFOLIO_COMMANDS + REPO_COMMANDS ).freeze
10
10
 
11
11
  def self.start( arguments:, repo_root:, tool_root:, output:, error: )
@@ -131,25 +131,19 @@ module Carson
131
131
  OptionParser.new do |parser|
132
132
  parser.banner = "Usage: carson <command> [options]\n carson <repo> <command> [options]"
133
133
  parser.separator ""
134
- parser.separator "Repository governance and workflow automation for coding agents."
135
- parser.separator ""
136
- parser.separator "Portfolio commands:"
137
- parser.separator " list List governed repositories"
138
- parser.separator " onboard Register a repository for governance (requires repo path)"
139
- parser.separator " offboard Remove a repository from governance (requires repo path)"
140
- parser.separator " refresh Re-install hooks and configuration (all governed repos)"
141
- parser.separator " version Show Carson version"
134
+ parser.separator "Keep agents from breaking main. Keep agents from breaking each other."
142
135
  parser.separator ""
143
136
  parser.separator "Agent workflow:"
144
- parser.separator " checkin Prepare a fresh workbench from the latest standard"
145
- parser.separator " deliver Ship committed work push, PR, merge, cleanup"
137
+ parser.separator " checkin Get a fresh workbench"
138
+ parser.separator " deliver Accept into main and back up to remote"
146
139
  parser.separator ""
147
- parser.separator "Repository commands (from CWD or with explicit repo):"
148
- parser.separator " checkout Release a workbench when done"
149
- parser.separator " status Show repository delivery state"
150
- parser.separator " audit Run pre-commit health checks"
140
+ parser.separator "Portfolio:"
141
+ parser.separator " onboard Start governing a repository"
142
+ parser.separator " offboard Stop governing a repository"
143
+ parser.separator " list Show governed repositories"
144
+ parser.separator " version Show Carson version"
151
145
  parser.separator ""
152
- parser.separator "Run `carson <command> --help` for details on a specific command."
146
+ parser.separator "Run `carson <command> --help` for details."
153
147
  end
154
148
  end
155
149
 
@@ -160,7 +154,7 @@ module Carson
160
154
  return { command: :help }
161
155
  end
162
156
  return { command: "version" } if [ "--version", "-v" ].include?( first )
163
- return { command: "audit" } if arguments.empty?
157
+ return { command: "status" } if arguments.empty?
164
158
 
165
159
  nil
166
160
  end
@@ -223,8 +217,6 @@ module Carson
223
217
  parse_sync_command( arguments: arguments, error: error )
224
218
  when "status"
225
219
  parse_status_command( arguments: arguments, error: error )
226
- when "audit"
227
- parse_audit_command( arguments: arguments, error: error )
228
220
  when "prune"
229
221
  parse_prune_command( arguments: arguments, error: error )
230
222
  when "housekeep"
@@ -290,7 +282,7 @@ module Carson
290
282
  parser.banner = "Usage: carson onboard <REPO_PATH>"
291
283
  parser.separator ""
292
284
  parser.separator "Register a repository for Carson governance."
293
- parser.separator "Detects the remote, installs hooks, applies templates, and runs initial audit."
285
+ parser.separator "Detects the remote, installs hooks, and applies templates."
294
286
  parser.separator ""
295
287
  parser.separator "Examples:"
296
288
  parser.separator " carson onboard ~/Dev/app Onboard a specific repository"
@@ -683,36 +675,6 @@ module Carson
683
675
  { command: :invalid }
684
676
  end
685
677
 
686
- # --- audit ---
687
-
688
- def self.parse_audit_command( arguments:, error: )
689
- options = { json: false }
690
- audit_parser = OptionParser.new do |parser|
691
- parser.banner = "Usage: carson audit [--json]"
692
- parser.separator ""
693
- parser.separator "Run pre-commit health checks on the repository."
694
- parser.separator "Validates hooks, main-branch sync, PR status, and CI baseline."
695
- parser.separator "Exits with a non-zero status when policy violations are found."
696
- parser.separator ""
697
- parser.separator "Options:"
698
- parser.on( "--json", "Machine-readable JSON output" ) { options[ :json ] = true }
699
- parser.separator ""
700
- parser.separator "Examples:"
701
- parser.separator " carson audit Check repository health (also the default command)"
702
- parser.separator " carson audit --json Structured output for agent consumption"
703
- end
704
- audit_parser.parse!( arguments )
705
- unless arguments.empty?
706
- error.puts "#{BADGE} Unexpected arguments for audit: #{arguments.join( ' ' )}"
707
- return { command: :invalid }
708
- end
709
- { command: "audit", json: options[ :json ] }
710
- rescue OptionParser::ParseError => exception
711
- error.puts "#{BADGE} #{exception.message}"
712
- error.puts audit_parser
713
- { command: :invalid }
714
- end
715
-
716
678
  # --- abandon ---
717
679
 
718
680
  def self.parse_abandon_command( arguments:, error: )
@@ -813,20 +775,20 @@ module Carson
813
775
 
814
776
  options = { json: false, title: nil, body_file: nil, commit_message: nil }
815
777
  deliver_parser = OptionParser.new do |parser|
816
- parser.banner = "Usage: carson deliver [--json] [--title TITLE] [--body-file PATH] [--commit MESSAGE]"
778
+ parser.banner = "Usage: carson deliver [--json] [--commit MESSAGE]"
817
779
  parser.separator ""
818
- parser.separator "Push the current branch, create or refresh the pull request, and hand the branch to Carson."
819
- parser.separator "Use --commit to create one all-dirty delivery commit before Carson pushes and opens the PR."
780
+ parser.separator "Accept committed work into main and sync to remote."
781
+ parser.separator "Use --commit to stage and commit all changes before delivery."
820
782
  parser.separator ""
821
783
  parser.separator "Options:"
822
784
  parser.on( "--json", "Machine-readable JSON output" ) { options[ :json ] = true }
823
- parser.on( "--title TITLE", "PR title (defaults to branch name)" ) { |value| options[ :title ] = value }
824
- parser.on( "--body-file PATH", "File containing PR body text" ) { |value| options[ :body_file ] = value }
825
- parser.on( "--commit MESSAGE", "Commit all dirty user changes before delivery" ) { |value| options[ :commit_message ] = value }
785
+ parser.on( "--title TITLE", "PR title (remote workstyle only)" ) { |value| options[ :title ] = value }
786
+ parser.on( "--body-file PATH", "PR body file (remote workstyle only)" ) { |value| options[ :body_file ] = value }
787
+ parser.on( "--commit MESSAGE", "Commit all changes before delivery" ) { |value| options[ :commit_message ] = value }
826
788
  parser.separator ""
827
789
  parser.separator "Examples:"
828
790
  parser.separator " carson deliver Deliver existing commits"
829
- parser.separator " carson deliver --commit \"fix: harden flow\" Commit dirty changes, then deliver"
791
+ parser.separator " carson deliver --commit \"fix: harden flow\" Commit then deliver"
830
792
  end
831
793
  deliver_parser.parse!( arguments )
832
794
  if options.fetch( :commit_message, nil ).to_s.strip.empty? && !options.fetch( :commit_message, nil ).nil?
@@ -860,7 +822,7 @@ module Carson
860
822
  parser.banner = "Usage: carson recover --check NAME [--json]"
861
823
  parser.separator ""
862
824
  parser.separator "Merge the current repair PR when one governance-owned required check is already red on the default branch."
863
- parser.separator "Recovery is narrow: Carson verifies the baseline failure, keeps every other gate intact, and records an audit event."
825
+ parser.separator "Recovery is narrow: Carson verifies the baseline failure, keeps every other gate intact, and records a recovery event."
864
826
  parser.separator ""
865
827
  parser.separator "Options:"
866
828
  parser.on( "--check NAME", "Name of the governance-owned required check to recover" ) { |value| options[ :check_name ] = value }
@@ -994,8 +956,6 @@ module Carson
994
956
  runtime.status!( json_output: parsed.fetch( :json, false ) )
995
957
  when "setup"
996
958
  runtime.setup!( cli_choices: parsed.fetch( :cli_choices, {} ) )
997
- when "audit"
998
- runtime.audit!( json_output: parsed.fetch( :json, false ) )
999
959
  when "abandon"
1000
960
  runtime.abandon!( target: parsed.fetch( :target ), json_output: parsed.fetch( :json, false ) )
1001
961
  when "sync"
@@ -1023,15 +983,15 @@ module Carson
1023
983
  when "template:apply"
1024
984
  runtime.template_apply!( push_prep: parsed.fetch( :push_prep, false ) )
1025
985
  when "deliver"
1026
- if runtime.config.workstyle == :local
1027
- dispatch_deliver_locally( parsed: parsed, runtime: runtime )
1028
- else
986
+ if runtime.config.bureau
1029
987
  runtime.deliver!(
1030
988
  title: parsed.fetch( :title, nil ),
1031
989
  body_file: parsed.fetch( :body_file, nil ),
1032
990
  commit_message: parsed.fetch( :commit_message, nil ),
1033
991
  json_output: parsed.fetch( :json, false )
1034
992
  )
993
+ else
994
+ dispatch_deliver_locally( parsed: parsed, runtime: runtime )
1035
995
  end
1036
996
  when "recover"
1037
997
  runtime.recover!(
@@ -1102,6 +1062,14 @@ module Carson
1102
1062
  json = parsed.fetch( :json, false )
1103
1063
  output = runtime.output
1104
1064
 
1065
+ # Guard: cannot deliver from main itself.
1066
+ if parcel.on_main?( runtime.config.main_branch )
1067
+ result = { command: "deliver", status: "block",
1068
+ error: "Cannot deliver from #{runtime.config.main_branch}.",
1069
+ recovery: "carson checkin <name>" }
1070
+ return report_deliver( result: result, json: json, output: output )
1071
+ end
1072
+
1105
1073
  # Step 1: Prepare.
1106
1074
  prep = warehouse.prepare!( parcel, message: message )
1107
1075
  unless prep[ :status ] == "ok"
@@ -1119,12 +1087,12 @@ module Carson
1119
1087
  return report_deliver( result: accept, json: json, output: output )
1120
1088
  end
1121
1089
 
1122
- # Step 3: Courier delivers backup.
1123
- courier = Courier.new( warehouse, workstyle: :local, output: output )
1124
- backup = courier.deliver( parcel )
1090
+ # Step 3: Courier syncs to remote.
1091
+ courier = Courier.new( warehouse, output: output )
1092
+ sync = courier.deliver( parcel )
1125
1093
 
1126
1094
  # Combine results.
1127
- result = accept.merge( backup.slice( :outcome, :synced, :backup_error ) )
1095
+ result = accept.merge( sync.slice( :outcome, :synced, :sync_error ) )
1128
1096
  result[ :command ] = "deliver"
1129
1097
  result[ :outcome ] ||= "delivered"
1130
1098
  report_deliver( result: result, json: json, output: output )
@@ -1146,9 +1114,9 @@ module Carson
1146
1114
  when "ok"
1147
1115
  output.puts "#{BADGE} #{result[ :branch ]} merged into main."
1148
1116
  if result[ :synced ]
1149
- output.puts "#{BADGE} Pushed to #{result.fetch( :remote_main, "remote" )}."
1150
- elsif result[ :backup_error ]
1151
- output.puts "#{BADGE} Backup failed."
1117
+ output.puts "#{BADGE} Synced to remote."
1118
+ elsif result[ :sync_error ]
1119
+ output.puts "#{BADGE} Sync failed."
1152
1120
  output.puts " \u2192 git push"
1153
1121
  end
1154
1122
  when "block", "error"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: carson
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.3.0
4
+ version: 4.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hailei Wang
@@ -57,7 +57,6 @@ files:
57
57
  - lib/carson/revision.rb
58
58
  - lib/carson/runtime.rb
59
59
  - lib/carson/runtime/abandon.rb
60
- - lib/carson/runtime/audit.rb
61
60
  - lib/carson/runtime/deliver.rb
62
61
  - lib/carson/runtime/housekeep.rb
63
62
  - lib/carson/runtime/list.rb