Architecture

Package layout

repairledger/
  __init__.py        Package version
  constants.py       Shared constants and enums (incl. global path config)
  errors.py          Structured error types
  models.py          Dataclass models (Workspace, Repair, ComponentSpec)
  identity.py        ID formatting, ref derivation, selector normalization
  storage.py         Filesystem operations, CRUD, version snapshots, locking
  guardrails.py      Validation for observed status
  render.py          Markdown rendering of repair artifacts
  report.py          Aggregate report generation
  bundle.py          Structured JSON bundle create/update
  cli.py             Typer CLI definition
  launcher.py        Entry point

Module dependencies

launcher → cli → { bundle, render, report, storage }
storage → { identity, constants, errors, models, guardrails }
bundle → { storage, identity, constants, errors }
render → { storage, identity, constants }
report → { storage, identity, constants }
identity → { constants } (via ledgercore refs)

Key design decisions

  • User-global config and data path: a single config at ${XDG_CONFIG_HOME:-~/.config}/ledger/repairledger.toml and a single data path at ${XDG_DATA_HOME:-~/.local/share}/ledger/repairledger/. Agents log observations from any repository without writing into the current source tree.

  • Global-only discovery: the local repository is never searched for a config. An absolute REPAIRLEDGER_CONFIG override is the only way to point at a custom config.

  • Flat package layout: No src/ directory. Package is directly under repo root.

  • Dynamic versioning: Via setuptools_scm from Git tags.

  • Atomic writes: All file mutations use ledgercore.atomic helpers.

  • Version snapshots: Complete post-mutation copies under versions/v000X/.

  • Derived refs: Global and file refs are generated at render time, not stored.

  • Inter-process locking: fcntl.flock against <data path>/.repairledger.lock serializes repair ID allocation, repair creation, and active-repair updates. Initialization uses a separate lock adjacent to the config file.

  • Explicit repair selector for mutations: when multiple repairs exist, mutating commands (repair status, repair archive, repair build, repair component set, repair component append) require an explicit --repair REPAIR_ID. The global active_repair_id is advisory only.

  • Read-only commands stay read-only: status, info, doctor, and next-action never create files. missing_storage is reported instead of silently adopting or creating storage.

  • ledgercore integration: Uses ledgercore for atomic I/O, YAML, ref parsing, timestamps, and hashing.