Imports:
  - Types:
      - sync AS sync_logic
    Usages:
      - sync-usages
    From: goga/usages
  - Types:
      - status AS status_logic
      - UsageStatusReport
      - DepStatus
      - EntryStatus
      - EntryChange
      - EntryKind
      - UsageState
    Usages:
      - usages-status
    From: goga/usages

Usages:
  click: .goga/usages/cooks/click.md
  convention: .goga/usages/conventions.md
  yaml: |
    Import the yaml module to catch yaml.YAMLError raised by load_project_config
    when converting config-load errors in the CLI wrappers.

Annotations: |
  The `convention` practice is used for:
  - Working with the codebase
  - Organizing the REPL development cycle
  - Debugging and testing
  - Organizing the test infrastructure
  - Understanding the general principles and rules of development and testing in the project
  Use the `click` practice to create the command group and subcommands.
  The commands delegate business logic through `sync_logic` and `status_logic`; consult the
  `sync-usages` and `usages-status` practices for their contracts (modes/statuses, on-disk
  result, exit codes).
  Use the `yaml` practice to catch yaml.YAMLError when the CLI wrappers convert a
  config-load error from `sync_logic`/`status_logic` into a clean click.ClickException.

---

"usages(group: str | None = None, dep: str | None = None)":
  location: usages.py
  annotations: |
    The goga usages command group — a click.Group container for usages subcommands.
    Exported via __all__ and registered in goga/cli.py. The sync and status subcommands are
    registered on this group per the `click` practice.

    The group carries --group/-g and --dep/-d as group-level click options (declared on
    the group callback; threaded to subcommands via @click.pass_context / ctx.parent.params,
    per the `click` practice).

    Use the `click` practice for the group decorator (@click.group()).
  methods:
    "sync(force: bool = False, group: str | None = None, dep: str | None = None) -> exit_code: int": |
      Subcommand goga usages sync: synchronize cell-level usages from declared git
      dependencies. Thin wrapper — delegates to `sync_logic`.

      `force`: --force/-f flag (click is_flag, default False) — clean then re-sync all deps.
      `group`: sourced from the group context (NOT a method-level @click.option) — the
        --group/-g value declared on the `usages` group callback.
      `dep`: sourced from the group context (NOT a method-level @click.option) — the
        --dep/-d value declared on the `usages` group callback.
      `exit_code`: propagated from `sync_logic` (0 success, 1 error).

      CLI option:
      - --force / -f: clean .goga/usages/ (except cooks and root *.md) then re-sync all

      Algorithm:
      1. Call `sync_logic`(`force`, `group`, `dep`) per the `sync-usages` practice
      2. If `sync_logic` propagates a config-load error (FileNotFoundError, KeyError,
         ValueError, or yaml.YAMLError raised by load_project_config) → raise
         click.ClickException(str(exc)) for a clean CLI error (exit 1), per the `yaml`
         practice for the YAMLError catch
      3. Return exit_code via ctx.exit

      Use the `click` practice for the subcommand and the --force/-f flag. The `group`/`dep`
      filters are read from the group context (declared on the group, not redeclared here).
    "status(info: bool = False, group: str | None = None, dep: str | None = None) -> exit_code: int": |
      Subcommand goga usages status: check synchronized cell-level usages against the current
      remote git state. Thin wrapper — delegates to `status_logic` and renders the result.

      `info`: --info/-i flag (click is_flag, default False) — expand each dep into its per-node
        file/folder entry tree with per-node status markers.
      `group`: sourced from the group context — the
        --group/-g value declared on the `usages` group callback.
      `dep`: sourced from the group context — the
        --dep/-d value declared on the `usages` group callback.
      `exit_code`: propagated from the report produced by `status_logic` (0 success, 1 drift/error).

      CLI options:
      - --info / -i: expand each dep into its per-node file/folder entry tree with per-node status markers

      Algorithm:
      1. Call `status_logic`(`group`, `dep`) — `group`/`dep` are read from the group context —
         per the `usages-status` practice → UsageStatusReport
      2. If `status_logic` propagates a config-load error (FileNotFoundError, KeyError,
         ValueError, or yaml.YAMLError raised by load_project_config) → raise
         click.ClickException(str(exc)) for a clean CLI error (exit 1), per the `yaml`
         practice for the YAMLError catch
      3. Render the report via `render_status_report`(report, `info`)
      4. Return exit_code via ctx.exit

      Use the `click` practice for the subcommand and the --info/-i option. The `group`/`dep`
      filters are read from the group context (declared on the group, not on status).

"render_status_report(report: UsageStatusReport, info: bool)":
  location: usages.py
  annotations: |
    Render a status report as a colored group → dep ASCII tree, with optional per-node
    entry expansion under --info.

    `report`: the aggregate status result
    `info`: when True, expand each dep into its per-node file/folder entry tree, each node
      carrying its own status marker

    Algorithm:
    1. Group `report`.deps by group; list the groups sorted
    2. For each group, print the group header (group name with a trailing slash); within the
       group, list the deps sorted by name, each rendered as a tree node carrying a bracketed
       status marker derived from its `DepStatus`.state — [ ] for unchanged/up to date, [*] for
       modified/out of date, [+] for new, [!] for error (an error dep additionally appends its
       credential-free message) — colored via the `click` practice
    3. When `info` is True, for each dep that carries entries, fold its flat `EntryStatus` list
       into a nested file/folder tree and print each node with its `EntryChange` marker — [ ]
       unchanged, [*] modified, [+] added, [-] removed; nodes whose `EntryKind` is a directory
       render with a trailing slash — sorted, colored via the `click` practice
    4. Apply color only to the changed markers ([*], [+], [-], [!]) — never to [ ] or the tree
       skeleton — and auto-disable color outside a TTY via the `click` practice

    Requirements:
    - Groups and the deps within each group are listed sorted
    - The dep state → marker mapping is consistent across `UsageState` values (new / out of
      date / error are visually distinct from up to date)

    Constraints:
    - Read-only on the report — do not mutate it
    - Do not compute statuses — render only what `report` already contains

---

Author: Goga
CreatedAt: 27/07/26
Description: |
  The goga usages command group with the sync and status subcommands.
