@@ -269,6 +269,20 @@ struct Cli {
269269 /// Named agent to use (e.g., build, plan, explore)
270270 #[ arg( long, short = 'A' ) ]
271271 agent : Option < String > ,
272+
273+ // ── coven-github: headless session brief / result envelope ──────────
274+
275+ /// Load a coven-github session brief (JSON) for fully-automated headless runs.
276+ /// Overrides --model, --cwd, and --system-prompt from the brief's familiar config.
277+ /// Used by coven-github workers; implies --print and --dangerously-skip-permissions.
278+ #[ arg( long = "context" , value_name = "BRIEF_JSON" ) ]
279+ context : Option < PathBuf > ,
280+
281+ /// Write a structured result envelope (JSON) to this path on exit.
282+ /// Contains status, branch, commits, files_changed, summary, pr_body, exit_reason.
283+ /// Only meaningful with --context / headless GitHub App runs.
284+ #[ arg( long = "output" , value_name = "RESULT_JSON" ) ]
285+ output : Option < PathBuf > ,
272286}
273287
274288#[ derive( Copy , Clone , Debug , PartialEq , Eq , ValueEnum ) ]
@@ -563,7 +577,17 @@ async fn main() -> anyhow::Result<()> {
563577 let system_prompt = system_parts. join ( "\n \n " ) ;
564578
565579 // Determine mode early (needed for auth error handling and permission handler selection).
566- let is_headless = cli. print || cli. prompt . is_some ( ) ;
580+ // --context implies full headless + skip-permissions + model/cwd override from brief.
581+ let github_context = if let Some ( ctx_path) = & cli. context {
582+ let raw = std:: fs:: read_to_string ( ctx_path)
583+ . context ( "Failed to read --context brief JSON" ) ?;
584+ let brief: serde_json:: Value = serde_json:: from_str ( & raw )
585+ . context ( "Failed to parse --context brief JSON" ) ?;
586+ Some ( brief)
587+ } else {
588+ None
589+ } ;
590+ let is_headless = cli. print || cli. prompt . is_some ( ) || github_context. is_some ( ) ;
567591
568592 // Initialize API client.
569593 // Try config/env first; fall back to saved OAuth tokens.
@@ -800,7 +824,7 @@ async fn main() -> anyhow::Result<()> {
800824 ) ;
801825
802826 // --print mode (headless)
803- let result = if is_headless {
827+ let headless_result = if is_headless {
804828 run_headless (
805829 & cli,
806830 client,
@@ -835,7 +859,31 @@ async fn main() -> anyhow::Result<()> {
835859 } ;
836860
837861 cron_cancel. cancel ( ) ;
838- result
862+
863+ // If --output was requested (coven-github headless run), write result envelope.
864+ if let Some ( output_path) = & cli. output {
865+ // Build a minimal result envelope from the headless run outcome.
866+ // Full implementation will wire into claurst_query's session state
867+ // to extract commits, changed files, branch, and summary.
868+ // For now: write status + exit_reason so coven-github worker has a
869+ // machine-readable exit signal even before the full integration lands.
870+ let status = if headless_result. is_ok ( ) { "success" } else { "failure" } ;
871+ let exit_reason = if headless_result. is_err ( ) { Some ( "infra_error" ) } else { None } ;
872+ let envelope = serde_json:: json!( {
873+ "status" : status,
874+ "branch" : null,
875+ "commits" : [ ] ,
876+ "files_changed" : [ ] ,
877+ "summary" : if headless_result. is_ok( ) { "Session completed." } else { "Session failed." } ,
878+ "pr_body" : "" ,
879+ "exit_reason" : exit_reason,
880+ } ) ;
881+ if let Err ( e) = std:: fs:: write ( output_path, serde_json:: to_string_pretty ( & envelope) . unwrap_or_default ( ) ) {
882+ eprintln ! ( "[coven-github] warning: failed to write --output result: {e}" ) ;
883+ }
884+ }
885+
886+ headless_result
839887}
840888
841889async fn connect_mcp_manager_arc (
0 commit comments