Imports:
  - Types:
      - HookRegistry
      - wrap_context
      - build_hook_arguments
      - declared_actions
    Usages:
      - per-tool-delivery
      - registering-hooks
    From: goga/hooks
  - Types:
      - ProjectConfig
      - BuildConfig
      - ReviewConfig
      - AdditionalReviewConfig
      - PipelineConfig
      - CodemanifestConfig
      - DepConfig
      - LintConfig
      - TopicsConfig
      - TopicsCreateConfig
      - TopicsUpdateConfig
      - TopicsPropagateConfig
    From: goga/config/project

Usages:
  convention: .goga/usages/conventions.md

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

  This cell owns the hooks zone of the config domain: the read-and-amend
  context of the project-configuration load moment, the deterministic
  in-memory amendment merge, and the checkpoint surface that delivers the
  amendment over the platform facade. One registry per run carries every
  checkpoint of a command — the checkpoints never multiply the package
  enumeration. Every context is built from the operation data the caller
  passes — no repository, git, or file reads happen here. The amendment
  action is hard: the first failing tool — a crashed hook or a
  structurally malformed contribution — stops the command with a clean
  error naming the tool and the action, and the tool's whole contribution
  is discarded. Tools are mutually blind — every amendment view reads the
  authored configuration, never another tool's staged or committed state;
  each tool's contributions commit as a unit, in enumeration order. The
  amendment lives in memory for the current run — the authored
  configuration file is never modified. The read view delivers the
  authored values — environment mappings included with their values;
  secrecy is enforced on the output side: no configuration value ever
  appears in the summary lines, warnings, or errors.
  Use the `per-tool-delivery` practice for the staged delivery loop of the
  amendment checkpoint — its loop skeleton, primitives, and tool-grouped
  commit apply as written.
  Use the `registering-hooks` practice for the hook signature and the
  failure handling behind the checkpoint.
  Use relative imports.

---

"ConfigAmendment(config: ProjectConfig)":
  location: amendments.py
  annotations: |
    The read-and-amend view of one tool — the delivered facts of the
    amendment checkpoint and the buffer of this tool's contributions.

    `config`: the authored loaded project configuration — values included,
               environment mappings included with their values

    Apply the `convention` practice for the data-model rules and
    intra-package imports.
    Use the `registering-hooks` practice for the hook signature that
    receives this view.

    Requirements:
    - The reads deliver the authored configuration — read-only and
      identical for every tool; a tool never sees another tool's
      contribution
    - The buffered contributions belong to this tool alone
  properties:
    "config -> ProjectConfig": |
      The authored loaded project configuration — the settings sections
      and their values, environment mappings included with their values;
      read-only for the receiving hook.
  methods:
    "set(path: str, value: str | int | bool | list[str])": |
      Buffer one amendment that applies only where the authored
      configuration is silent at the path.

      `path`: the dotted leaf path in the authored vocabulary
      `value`: the amendment value

      Requirements:
      - The call buffers into the buffer of this tool alone and changes
        nothing until the delivery commits it
      - A later amendment of this tool on the same path replaces its
        earlier one
      - A set on a path where the authored configuration is not silent
        is dropped silently — not an error, no warning

      Constraints:
      - Do not cancel, redirect, or defer the operation — an amendment
        transforms the effective configuration layer only
    "force(path: str, value: str | int | bool | list[str])": |
      Buffer one amendment that overwrites the authored value at the
      path — the tool's explicit override intent.

      `path`: the dotted leaf path in the authored vocabulary
      `value`: the amendment value

      Requirements:
      - The call buffers into the buffer of this tool alone and changes
        nothing until the delivery commits it
      - A later amendment of this tool on the same path replaces its
        earlier one

      Constraints:
      - Do not cancel, redirect, or defer the operation — an amendment
        transforms the effective configuration layer only

"PathAmendment(path: str, intent: str, value: str | int | bool | list[str])":
  location: amendments.py
  annotations: |
    One buffered amendment — the addressed leaf path, the intent, and the
    value.

    `path`: the dotted leaf path in the authored vocabulary
    `intent`: exactly set or force
    `value`: the amendment value

    Apply the `convention` practice for the data-model rules and
    intra-package imports.

    Requirements:
    - Pure data — constructed by the amendment buffer alone

"ToolAmendment(tool: str, amendments: list[PathAmendment])":
  location: overlay.py
  annotations: |
    The committed contribution of one tool — the pairing of the tool
    identity with its ordered path amendments.

    `tool`: the tool identity assigned by the platform
    `amendments`: the committed contributions of the tool, in buffer
                   order

    Apply the `convention` practice for the data-model rules and
    intra-package imports.

"AppliedAmendment(tool: str, path: str, intent: str)":
  location: overlay.py
  annotations: |
    One applied amendment — the winning contribution of one path.

    `tool`: the tool identity whose amendment won the path
    `path`: the applied dotted leaf path
    `intent`: exactly set or forced

    Apply the `convention` practice for the data-model rules and
    intra-package imports.

    Requirements:
    - Carries no value — no configuration value travels into any output

"ConfigOverlay(config: ProjectConfig, applied: list[AppliedAmendment])":
  location: overlay.py
  annotations: |
    The result of the amendment layer — the effective configuration and
    its applied amendments.

    `config`: the effective (in-memory, per-run) configuration
    `applied`: the applied amendments in enumeration order — one record
                per applied path, the winning amendment

    Apply the `convention` practice for the data-model rules and
    intra-package imports.

    Requirements:
    - The effective configuration is a `ProjectConfig` — every downstream
      consumer of the run observes it
  properties:
    "config -> ProjectConfig": |
      The effective configuration of the run — the authored configuration
      with the applied amendments merged in memory.
    "applied -> list[AppliedAmendment]": |
      The applied amendments in enumeration order — one record per
      applied path.
    "summary_lines -> list[str]": |
      The composed amendment summary — one header line plus one line per
      applied amendment (the tool, the path, set or forced), in
      enumeration order; empty when nothing applied. No configuration
      value ever appears in a line.

"merge_config_amendments(base: ProjectConfig, contributions: list[ToolAmendment]) -> overlay: ConfigOverlay":
  location: overlay.py
  annotations: |
    The deterministic amendment merge — compose the effective
    configuration from the authored base and the committed tool
    contributions.

    `base`: the authored loaded configuration
    `contributions`: the committed contributions in enumeration order
    `overlay`: the effective configuration with the applied amendments

    Apply the `convention` practice for docstring style and
    intra-package imports.

    Algorithm:
    1. Validate every amendment of every contribution against the
       configuration model's type tree — the fields of `ProjectConfig`
       and of the section models `BuildConfig`, `ReviewConfig`,
       `AdditionalReviewConfig`, `PipelineConfig`, `CodemanifestConfig`,
       `DepConfig`, `LintConfig`, `TopicsConfig`, `TopicsCreateConfig`,
       `TopicsUpdateConfig`, `TopicsPropagateConfig`, with arbitrary keys
       admitted under mapping-typed fields. A path is known iff it
       resolves to a leaf of the tree: a scalar leaf, a list-valued leaf,
       or an individual mapping entry. An unknown path, a non-leaf
       address, or a value of the wrong type at the node is a structural
       failure of the contributing tool — raise naming the tool and the
       malformedness; no amendment of the run applies. The
       usages.<group>.<dep> leaves additionally carry the loader's own
       structural rules: a group or dep segment must be a plain name
       (no path separator, no dot or dot-dot traversal segment), git and
       ref non-empty strings stored stripped as the loader stores
       them, and root a safe relative subpath — a blank root carries
       no root
    2. Resolve each path deterministically: authored silence at a path
       means the loaded model carries an absence marker — None, an empty
       mapping, or an empty list; authored emptiness loses to set. A set
       on a non-silent authored path is dropped silently. On one path
       force beats any set regardless of enumeration order; among
       amendments of equal intent the later tool in enumeration order
       wins
    3. Compose the effective configuration: apply each winning amendment
       to the `base` in memory — materialize the missing intermediate
       nodes of a model-known path, replace list-valued leaves wholesale,
       set individual mapping entries, reconstruct the affected
       configuration instances. A final pass over the finished
       composition rejects a dep the composition materialized under
       usages whose git is still missing — the same structural
       failure of the first applied tool under the branch,
       order-independent
    4. Collect one `AppliedAmendment` per applied path — the winning
       tool, the path, set or forced — in enumeration order
    5. Return the `ConfigOverlay`

    Requirements:
    - Deterministic — the same base and the same contributions give the
      same overlay
    - Pure — the inputs stay unmutated; the result is a new
      configuration
    - The commands mapping is free-form — any key under it addresses a
      value without a node type check
    - The result is a structurally valid configuration — every applied
      value matches the node it landed on
    - The usages amendment paths carry the loader's own structural
      rules — plain group/dep names, non-empty git/ref stored
      stripped, a safe relative root; a dep materialized by the
      composition without its required git fails the merge

    Constraints:
    - Do not read or write the filesystem — the authored file stays
      untouched
    - Do not validate the semantics of well-formed values — the consumers
      own semantic validation
    - Do not mutate `base`, the contributions, or their collections

"ConfigHooks()":
  location: events.py
  annotations: |
    The checkpoint surface of the config domain — the amendment delivery
    over the platform facade.

    Apply the `convention` practice for the code style and intra-package
    imports.
    Use the `per-tool-delivery` practice for the staged delivery loop of
    the amendment checkpoint.
    Use the `registering-hooks` practice for the registration contract
    behind the checkpoint.

    Requirements:
    - Cheap construction — no enumeration and no imports happen at
      construction
    - One `HookRegistry` per run carries every checkpoint of a command —
      the assembly runs once per run whatever the number of checkpoints
    - Every context is built from the values the caller passes — no
      repository, git, or file reads happen at the checkpoint
  methods:
    "amend_config(config: ProjectConfig) -> overlay: ConfigOverlay": |
      Deliver the config-amendment checkpoint and return the effective
      configuration with its applied amendments.

      `config`: the authored loaded project configuration — operation
                 data handed over by the calling command
      `overlay`: the effective configuration and the applied amendments

      Use the `per-tool-delivery` practice for the delivery loop.

      Algorithm:
      1. Resolve the address domain="config", action="amend_config"
         against `declared_actions`
      2. Walk the subscriptions of the address per tool in enumeration
         order: build the tool's `ConfigAmendment` view over the
         delivered facts — every tool reads the same authored `config` —
         wrap it via `wrap_context`, project the call arguments via
         `build_hook_arguments` with the tool's own context, and call
         each hook of the tool
      3. A tool whose every hook returned without raising commits as one
         `ToolAmendment` — a tool whose buffer carries no amendment
         commits nothing
      4. A tool with a raising hook is a hard failure: a clean error
         naming the tool and the action stops the command at the first
         failure; the tool's contribution is discarded
      5. Merge the committed contributions onto `config` via
         `merge_config_amendments`; a structural failure raised there is
         the same hard failure — the clean error names the tool and the
         action, nothing applies
      6. Return the overlay

      Requirements:
      - The commit granularity is the tool — a tool's whole contribution
        commits only after every hook of the tool succeeds
      - An address without subscriptions returns the passthrough overlay
        — the configuration passed in, an empty applied list, empty
        summary lines; the delivery is unobservable
      - With no tool packages installed the load composes exactly what
        was passed

      Constraints:
      - Do not apply any contribution outside the single merge after the
        walk
      - Do not skip a subscriber of the address
      - Do not read repositories, git, or the filesystem at the checkpoint
      - Do not print — the summary lines are data; the caller acts on
        them

---

Author: Goga
CreatedAt: 22/09/26
Description: |
  Owner of the config domain hooks zone — the read-and-amend context, the
  in-memory amendment merge, and the checkpoint surface over the hooks
  platform.
