packages feed

gachi-cli-0.1.0.1: src/Gachi/CLI.hs

{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE OverloadedStrings #-}

-- | Module: Gachi.CLI
-- Description: Unified front-door dispatcher and entry point for gachi
--
-- This is the root library module for @gachi-cli@. It provides top-level command
-- line argument parsing, dispatching, version reporting, and error handling.
--
-- = Architectural Context & Invariants
--
-- Gachi serves as the foundational project skeleton generator and configuration
-- propagation engine across the ecosystem (per Note [Ecosystem Standardization Invariants]
-- [ref:note-ecosystem-standardization]).
--
-- == Operational Architecture
--
-- This module acts as the primary orchestrator and dispatcher across all CLI subcommands:
--
-- 1. __Argument Processing:__
--    Uses @optparse-applicative@ configured with 'showHelpOnEmpty' to display context-aware
--    usage hints whenever an empty invocation or ambiguous argument sequence is detected.
--
-- 2. __Execution Lifecycle:__
--    Dispatches parsed 'Command' representations to their specialized execution modules.
--    'CmdInit' delegates to 'runInit' in "Gachi.CLI.Init", while placeholder routines
--    for Phase 3 ('CmdSync'), Phase 4 ('CmdRetrofit'), and Phase 5 ('CmdPlan') provide
--    informative scheduling notices without failing abruptly.
--
-- 3. __Exit Code Normalization:__
--    Every subcommand produces a deterministic 'ExitCode' ('ExitSuccess' or 'ExitFailure'),
--    ensuring predictable interaction with shell scripts, CI runners, and pre-commit hooks.
--
-- = Command Matrix
--
-- * 'gachi init': Full turnkey multi-package repository materialization (Milestone 2.3).
-- * 'gachi sync': Bidirectional configuration synchronization (Phase 3).
-- * 'gachi retrofit': Non-destructive legacy codebase upgrade (Phase 4).
-- * 'gachi plan': Detached git snapshotting and rollback (Phase 5).
-- * 'gachi version': Compiler and tooling pinning diagnostics.
--
-- = Worked Example
--
-- >>> import Gachi.CLI
-- >>> -- Invoked from executable Main:
-- >>> -- defaultMain
module Gachi.CLI
  ( -- * Main CLI Dispatcher
    defaultMain
  , runCommand

    -- * Package Metadata
  , gachiVersion

    -- * Re-exports
  , module Gachi.CLI.Doctor
  , module Gachi.CLI.Init
  , module Gachi.CLI.Options
  , module Gachi.CLI.Retrofit
  , module Gachi.CLI.Sync
  ) where

import Data.Text (Text)
import qualified Data.Text.IO as TIO
import Options.Applicative (customExecParser, prefs, showHelpOnEmpty)
import System.Exit (ExitCode(..), exitWith)

import Gachi.CLI.Doctor
  ( checkBinaryVersion
  , checkToolchainHealth
  , formatToolchainStatus
  , runDoctor
  , runSheafAudit
  )
import Gachi.CLI.Init
  ( detectGitAuthor
  , executeScaffolding
  , initializeGitRepository
  , promptUser
  , resolveProject
  , runInit
  )
import Gachi.CLI.Options
  ( Command(..)
  , DoctorOptions(..)
  , InitOptions(..)
  , PlanOptions(..)
  , RetrofitOptions(..)
  , SyncOptions(..)
  , commandParser
  , doctorOptionsParser
  , initOptionsParser
  , parseMode
  , parsePackageList
  , planOptionsParser
  , retrofitOptionsParser
  , syncOptionsParser
  )
import Gachi.CLI.Retrofit (runRetrofit)
import Gachi.CLI.Sync (runSync)

--------------------------------------------------------------------------------
-- 1. Metadata
--------------------------------------------------------------------------------

-- | Canonical version identifier for the gachi toolchain.
gachiVersion :: Text
gachiVersion = "0.1.0.1"

--------------------------------------------------------------------------------
-- 2. Top-Level Entry Points
--------------------------------------------------------------------------------

-- | High-level executable entry point.
--
-- Parses ambient command-line arguments using 'commandParser' and delegates
-- to 'runCommand', terminating the process with the resulting 'ExitCode'.
defaultMain :: IO ()
defaultMain = do
  let parserPrefs = prefs showHelpOnEmpty
  cmd <- customExecParser parserPrefs (commandParser gachiVersion)
  code <- runCommand cmd
  exitWith code

-- | Pure/IO command dispatcher executing a parsed 'Command'.
--
-- Maps high-level AST commands to operational routines:
--
-- * 'CmdInit': Dispatches directly to 'runInit', executing the complete project
--   synthesis, filesystem materialization, and Git governance lifecycle.
-- * 'CmdSync': Dispatches directly to 'runSync', harmonizing configuration and
--   governance stanzas across single repositories or the entire ecosystem.
-- * 'CmdRetrofit': Dispatches directly to 'runRetrofit', executing diagnostic
--   repository inspection (Milestone 4.1) and non-destructive overlay synthesis (Phase 4).
-- * 'CmdPlan': Emits roadmap schedule notice for Phase 5 detached Git ledger governance.
-- * 'CmdVersion': Outputs compiler pinning, Cabal target, and EUPL-1.2 licensing stanzas.
--
-- Guarantees total evaluation with deterministic exit code propagation.
runCommand :: Command -> IO ExitCode
runCommand (CmdInit opts) = runInit opts
runCommand (CmdSync opts) = runSync opts
runCommand (CmdDoctor opts) = runDoctor opts
runCommand (CmdRetrofit opts) = runRetrofit opts
runCommand (CmdPlan _opts) = do
  TIO.putStrLn "gachi plan: Detached Git store & snapshot rollback engine (Phase 5 - Scheduled)"
  pure ExitSuccess
runCommand CmdVersion = do
  TIO.putStrLn ("gachi v" <> gachiVersion <> " (GHC 9.14.1 / Cabal 3.18 / EUPL-1.2)")
  pure ExitSuccess