package app import ( "context" "flag" "fmt" "io" "strings" "gitea.maximumdirect.net/eric/narratio/internal/artifacts" "gitea.maximumdirect.net/eric/narratio/internal/config" ) // Status reports effective local/remote session state. func Status(ctx context.Context, args []string, out io.Writer) error { fs := flag.NewFlagSet("status", flag.ContinueOnError) fs.SetOutput(io.Discard) var flags commonConfigFlags addCommonConfigFlags(fs, &flags) if err := parseSessionAwareFlags("status", fs, args, &flags.sessionID); err != nil { return err } if strings.TrimSpace(flags.sessionID) == "" { return fmt.Errorf("status: session_id is required") } cfg, err := loadCommandConfig(ctx, flags.pipelinePath, flags.campaignPath, flags.campaignFilePath, flags.sessionPath, flags.sessionOptions()) if err != nil { return fmt.Errorf("status: %w", err) } if err := config.Validate(cfg); err != nil { return fmt.Errorf("status: %w", err) } paths := artifacts.NewLocalStore(cfg.Pipeline.Workspace.Root).SessionPathsFor(cfg.Session.Campaign, cfg.Session.SessionID) fmt.Fprintf(out, "Session: %s\n", cfg.Session.SessionID) fmt.Fprintf(out, "Campaign: %s\n", cfg.Session.Campaign) fmt.Fprintf(out, "Workspace: %s\n", paths.Root) fmt.Fprintf(out, "Session config: %s\n", sessionSourceSummary(cfg)) if m, err := loadLocalManifest(ctx, paths.ManifestPath); err != nil { fmt.Fprintf(out, "Local manifest: error: %v\n", err) } else if m == nil { fmt.Fprintln(out, "Local manifest: missing") } else { fmt.Fprintf(out, "Local manifest: %s\n", paths.ManifestPath) writeStageStatuses(out, m) } store, storeErr := objectStoreIfConfigured(ctx, cfg) if storeErr != nil { fmt.Fprintf(out, "Remote publish: unavailable: %v\n", storeErr) } else if store != nil { current, err := discoverRemoteCurrentStateFn(ctx, cfg, store) if err != nil { fmt.Fprintf(out, "Remote publish: missing or unavailable: %v\n", err) } else { fmt.Fprintf(out, "Remote publish: current run %s\n", current.RunID) fmt.Fprintf(out, "Remote manifest: %s\n", current.CurrentManifestKey) } } locks, err := loadEffectiveLocks(ctx, cfg, store) if catalog, catalogErr := buildHelperArtifactCatalog(cfg); catalogErr != nil { fmt.Fprintf(out, "Remote outputs: error: %v\n", catalogErr) } else if storeErr == nil { catalogLocks := locks if err != nil { catalogLocks = &effectiveLocks{ Static: staticPublishLocks(cfg), All: staticPublishLocks(cfg), } } publishedRemoteState := map[string]string{} if store != nil { publishedRemoteState = remotePublishedOutputAvailability(ctx, cfg, store, catalog) } fmt.Fprintln(out, "Remote outputs:") writeArtifactList(out, cfg, catalog, catalogLocks, publishedRemoteState) } if err != nil { fmt.Fprintf(out, "Publish locks: error: %v\n", err) } else { writeLocks(out, cfg, locks) } fmt.Fprintln(out, "Next actions:") fmt.Fprintf(out, "- narratio session validate %s\n", cfg.Session.SessionID) fmt.Fprintf(out, "- narratio session restore %s --dry-run\n", cfg.Session.SessionID) return nil }