Metadata-Version: 2.4
Name: goga
Version: 2.0.0
Summary: A tool for working with the codemanifest specification — assembly, extension, and plan-building workflow
License: BSD-3-Clause
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: pip
Requires-Dist: click>=8.0
Requires-Dist: copier>=9.0
Requires-Dist: pyyaml>=6.0
Requires-Dist: requests>=2.28.0
Requires-Dist: tree-sitter>=0.25.2
Requires-Dist: tree-sitter-go>=0.25.0
Requires-Dist: tree-sitter-javascript>=0.25.0
Requires-Dist: tree-sitter-swift>=0.7.2
Requires-Dist: tree-sitter-kotlin>=1.1.0
Requires-Dist: tree-sitter-python>=0.25.0
Requires-Dist: goga-tool-viewer<1.1.0,>=1.0.0
Requires-Dist: goga-tool-mkdocs<1.1.0,>=1.0.0
Requires-Dist: goga-tool-scriba<1.1.0,>=1.0.0
Provides-Extra: test
Requires-Dist: pytest>=8.0; extra == "test"
Requires-Dist: pytest-cov>=5.0; extra == "test"
Requires-Dist: ruff>=0.15.0; extra == "test"
Provides-Extra: docs
Requires-Dist: mkdocs>=1.6.0; extra == "docs"
Requires-Dist: mkdocs-material>=9.5.0; extra == "docs"
Dynamic: license-file

<div align="center">

<img src="docs/assets/goga.svg" alt="goga" width="180" />

# Goga

An open platform for building AI-SDLC.

AI can already write code. The next problem is engineering the process around it.

Goga turns engineering processes into reusable software. Define them as pipelines, package capabilities as tools, use any CLI agent at any stage — and share the whole methodology across projects.

A full Specification-Driven Development (SDD) cycle ships in the box — it can run interactively with a human in the loop or autonomously as a harness.

**Three pillars**

<table>
  <tr>
    <td width="33.33%" align="left" valign="top">
      <h3>⚙ Pipelines</h3>
      <p>A declarative scenario of stages an agent walks through to deliver work, with <code>communication</code> checkpoints that switch between autonomous and human-in-the-loop execution. Any installed agent (Claude, Codex, Qwen, OpenCode, others) can be hired per stage.</p>
    </td>
    <td width="33.33%" align="left" valign="top">
      <h3>🧩 Tools</h3>
      <p>Pluggable capability packages. Any open-source tool or in-house methodology is packaged as <code>goga-tool-*</code> and lands in a shared catalog of skills and pipelines, all addressed uniformly.</p>
    </td>
    <td width="33.33%" align="left" valign="top">
      <h3>📋 SDD</h3>
      <p>The reference cycle shipped in the box: <a href="https://github.com/qarium/codemanifest/blob/0.0.x/specs/en.md"><strong>CODEMANIFEST</strong></a> contracts as the source of truth, an agent workflow from <code>specify</code> to <code>accept</code>. Use it as is, extend it through workflows, or replace it with your own methodology built from tools and pipelines.</p>
    </td>
  </tr>
</table>

AI development without a framework collapses into uncoordinated agent runs — the cycle cannot be reproduced, there are no managed approval checkpoints, and the methodology is locked into a single tool. goga is the framework: the process is declared, agents are interchangeable, methodologies are composable.

**Languages**

<table>
  <tr>
    <td align="center"><sub>Python</sub><br><img src="docs/assets/brands/python.svg" alt="Python" width="40" height="40"></td>
    <td align="center"><sub>JavaScript</sub><br><img src="docs/assets/brands/javascript.svg" alt="JavaScript" width="40" height="40"></td>
    <td align="center"><sub>Kotlin</sub><br><img src="docs/assets/brands/kotlin.svg" alt="Kotlin" width="40" height="40"></td>
    <td align="center"><sub>Swift</sub><br><img src="docs/assets/brands/swift.svg" alt="Swift" width="40" height="40"></td>
    <td align="center"><sub>Go</sub><br><img src="docs/assets/brands/go.svg" alt="Go" width="40" height="40"></td>
  </tr>
</table>

**Agents**

<table>
  <tr>
    <td align="center"><sub>Claude</sub><br><img src="docs/assets/brands/claude.svg" alt="Claude" width="40" height="40"></td>
    <td align="center"><sub>Codex</sub><br><img src="docs/assets/brands/openai.svg" alt="Codex" width="40" height="40"></td>
    <td align="center"><sub>OpenCode</sub><br><img src="docs/assets/brands/opencode.svg" alt="OpenCode" width="40" height="40"></td>
    <td align="center"><sub>Cursor</sub><br><img src="docs/assets/brands/cursor.svg" alt="Cursor" width="40" height="40"></td>
    <td align="center"><sub>Qwen</sub><br><img src="docs/assets/brands/qwen.svg" alt="Qwen" width="40" height="40"></td>
  </tr>
</table>

[Documentation](https://qarium.github.io/goga/) · [Getting Started](https://qarium.github.io/goga/getting-started/) · [Pipelines](https://qarium.github.io/goga/features/pipelines/) · [Tools](https://qarium.github.io/goga/features/tools/) · [Configuration](https://qarium.github.io/goga/configuration/)

</div>

---

## Install

```bash
pipx install goga
```

`goga build` and `goga pipeline` launch a Docker container, so Docker must be installed and accessible on your host:

```bash
docker info
```

Before each launch they also verify that the host goga version and the image's goga version agree at the (major, minor) level — set `GOGA_SKIP_VERSION_CHECK=1` to skip the check, and run `goga --version` to print the installed host version.

Connect goga to your agent

```bash
goga connect <agent>
```

To upgrade goga later and re-sync all connected agents, use:

```bash
goga upgrade
```

To stay within your current version line while upgrading, use `goga upgrade --patch` (latest patch of the installed minor line) or `goga upgrade --minor` (latest release of the installed major line). See [`goga upgrade`](https://qarium.github.io/goga/features/upgrade/cli/) for the full surface.

## Quick start

Start a new project from scratch and ship your first piece of work end-to-end.

**1. Initialize the project** — the interactive wizard sets up `.goga/config.yml`, language conventions, and (optionally) a `Dockerfile`:

```bash
goga init
```

You can also start from a [copier](https://copier.readthedocs.io/) template (`goga init <template-url>`, optionally pinned with `#ref` or `--ref`), and later migrate a scaffolded project with `goga init --upgrade`. Installed tools can be invited into the wizard with `goga init -t <tool-name>` (repeatable) — the tool then contributes its own questions and its config files under `.goga/tools/<tool>/`. See [`goga init`](https://qarium.github.io/goga/features/init/cli/) for the full surface.

**2. Open your agent** — launch the agent you connected via `goga connect` (e.g., Claude Code) in the project directory. All `goga-<command>` skills are now available.

**3. Run a pipeline** — pick one of the shipped cycles and let goga walk the agent through its stages, pausing at every `communication` checkpoint for your input. The container mounts nothing automatically: give it access to your agent credentials yourself — a read-only volume token in the `docker.run` list of `~/.goga/config.yml`, or the agent's API-key env var with `-e` (see [Credentials in the container](https://qarium.github.io/goga/features/pipelines/runtime/#credentials)):

```bash
goga pipeline refinement     # product definition: define → discover → specify → review
goga pipeline development    # the development cycle: prototype-architecture → … → accept
goga pipeline bugfix         # root-cause analysis and defect resolution
goga pipeline patch          # refactoring or minimal change with a plan
goga pipeline review         # scoped review of code, contracts, docs, then lint/format/tests
goga pipeline sync           # sync specifications & tests with the code after changes
```

Each pipeline is a flat YAML file describing the stages; layer project-specific behavior on top via an optional [workflow](https://qarium.github.io/goga/features/pipelines/workflows/) file (per-stage agent, additional skills, prompt context, loop expansion, auto-approval, manual stage launch, stage skipping, note buttons, new stages, project-memory participation).

**4. Drive the cycle by hand (optional)** — if you want explicit control over each step instead of running a full pipeline, formulate the task and step through each command manually:

```text
/goga:specify <what you want to create>
```

```
specify → prototype → apply → design → plan → goga build → change → accept
```

The slash-command form `/goga:<command>` works in agents that consume the goga command bundle — currently `claude`, `opencode`, and `qwen` (see [`goga connect`](https://qarium.github.io/goga/features/connect/cli/)). Codex and cursor do not register commands; in those agents invoke the skill directly: `goga-specify` (Codex uses the `$` prefix — `$goga-specify`). Reviews are optional at every stage.

**5. Visualize the result** — once `apply` has produced cells on disk, inspect the architecture:

```bash
goga schema | goga tool viewer
```

## Pipelines

A **pipeline** is a declarative scenario of stages an agent walks through to deliver a piece of work — specify, review, prototype, apply, design, plan, build, change, accept. A pipeline-file does not depend on any concrete agent: claude, codex, qwen, opencode, or any other installed wrapper can execute it. Stages with `communication: true` pause the run and ask for human input; without it they run autonomously.

A pipeline-file is a flat YAML document with a header and a list of stages:

```yaml
name: Feature
description: End-to-end feature development
---

- name: specify
  title: "Create the task from a user specification"
  communication: true
  prompt: |
    Save the task file as `.goga/history/<year>/<topic>/task.md`
    (`<year>` = current year, `YYYY`; `<topic>` = lowercase kebab-case slug
    of the current git branch name; create the directory lazily)
  skills:
    - goga-specify

- name: prototype
  title: "Task-based architecture development"
  communication: true
  skills:
    - goga-prototype

- name: accept-result
  title: "Contracts & coverage audit"
  communication: true
  skills:
    - goga-accept
```

Six definitions ship with goga:

| Pipeline      | Purpose                                                                  |
|---------------|--------------------------------------------------------------------------|
| `development` | End-to-end development lifecycle: architecture, design, plan, accept     |
| `refinement`  | Product definition and task refinement: define, discover, specify        |
| `bugfix`      | Root-cause analysis and resolution for a defect                          |
| `patch`       | Refactoring or minimal change with a formalized plan                     |
| `review`      | Scoped review of code, contracts, docs, then lint/format/tests           |
| `sync`        | Sync specifications and tests with the implementation                    |

Pipelines are resolved from `<cwd>/.goga/pipelines/` (project) and `~/.goga/pipelines/` (user); the project source wins on name conflicts.

```bash
goga pipeline development             # run the development cycle (opens with prototype-architecture)
goga pipeline development -t feat/x   # first switch to the branch hosting this work, then run
goga pipeline refinement -s discover  # shorter run: skip technical discovery
goga pipeline development -p 4        # cap parallelism (subject to the pipeline's dependency rules)
goga pipeline development --clean     # wipe persistent state for a fresh run
```

Inspect pipelines without running anything:

```bash
goga pipeline --list                              # available pipeline names
goga pipeline --list --info                       # every pipeline with its description
goga pipeline development --info                  # the pipeline card: stages in execution order
goga pipeline development --info -s prototype-architecture    # the card with a stage excluded — the composition the run would execute
```

A running pipeline executes inside a Docker container, where its flows, run-state, and logs are written to a persistent host directory and survive across runs of the same pipeline on the same project and branch — so an interrupted run can be resumed.

### Workflows — configure and extend a pipeline

A **workflow-file** (`.goga/workflows/<name>.yml`) configures and extends a compiled pipeline at run time, without touching the pipeline-file. Eight levers, each with a short example.

**`agent` — hire a different agent per stage.** Authoring on `codex`, reviews on `claude`, no pipeline duplication:

```yaml
stages:
  prototype-architecture:
    agent: codex
  architecture-review:
    agent: claude
  plan-review:
    agent: claude
```

**`loop` — repeat a stage N times as chained copies.** Multiple review passes with increasing depth:

```yaml
stages:
  plan-review:
    loop: 2       # → plan-review-1 → plan-review-2, each depending on the previous
```

**`approve` — auto-approve a stage.** Three modes (`auto` / `plan` / `dialog`) drive two independent effects — suppression of `interactive` and emission of `auto_approve`:

```yaml
stages:
  accept-result:
    approve: auto   # the stage will not prompt the user and will self-approve
```

**`manual` — hold a stage for manual launch.** `manual: true` compiles the stage with `auto_run: false` — the run pauses when it reaches the stage and continues only after you launch it; `manual: false` cancels a `trigger: manual` authored in the stage body:

```yaml
stages:
  accept-result:
    manual: true    # the pipeline pauses before accept-result until launched manually
```

**`skills` — add skills to a stage.** Merged with the pipeline stage's own skills (pipeline-first, deduplicated by value):

```yaml
stages:
  prototype-architecture:
    skills: [goga-tool-acme-explore, goga-tool-acme-propose]
```

**`prompt` — context, not command.** To make a workflow `prompt` carry actual requirements, use labeled blocks (`Requirements:` / `Constraints:`); free-form prose is interpreted as background:

```yaml
stages:
  specify:
    prompt: |
      Task formalization process.

      Requirements:
      - Examine all link connections between cells carefully.
      - Do not write code examples in the task.

      Constraints:
      - Do not build architecture in the task.
```

**`notes` — attach note buttons to a stage.** A map of note name → prompt text, compiled verbatim into the stage's `buttons` field:

```yaml
stages:
  plan-review:
    notes:
      fix: Fix the failure and continue
```

**`memory` — wire stages into project memory.** A top-level block plus per-stage instructions; the block is emitted only when at least one stage participates:

```yaml
memory:
  method: reflect       # or: alignment
  max_rules: 40
stages:
  prototype-architecture:
    reflect:            # which memory file the stage reflects into
      file: shared.md
```

Additionally: `skip: true` removes a stage with transparent reconnection of dependents, and `extend:` adds brand-new stages with `before`/`after` positioning (a new stage's own launch mode is authored in its body via `trigger: manual`). Names under `stages:` must name stages of the target pipeline — `specify` exists only in `refinement`, `prototype-architecture` only in `development`; brand-new stages come via `extend:`. The full model is in the [Workflows](https://qarium.github.io/goga/features/pipelines/workflows/) documentation. Workflow memory requires afm 0.5.60+ (the shipped image carries it).

Run with a workflow:

```bash
goga pipeline development                    # auto-match: .goga/workflows/development.yml if present
goga pipeline development --workflow custom  # explicit
goga pipeline development --no-workflow      # disable workflow application entirely
```

Read the full functional model in the [Pipelines](https://qarium.github.io/goga/features/pipelines/) section of the docs.

## Build

`goga build` is a separate service that materializes a plan into code. Pipelines produce plans; Build executes them — and neither side is a special case of the other. A plan is handed to a ralph-loop running inside an isolated Docker container, which reads the plan, executes each task in sequence (declaration → contract tests → implementation → interface verification → logic tests → debugging → contract re-verification → lint → review → approval), and writes the implementation into the project tree. `CODEMANIFEST` files stay **read-only** throughout — the contract is the source of truth, the build produces code that satisfies it.

```bash
goga build .goga/history/<year>/<topic>/plan.md
```

The host side assembles the environment and launches the container; the in-container process then guards its environment, prepares the loop's working directory, and runs the loop with the plan as input. The launcher adds no credential mounts — mount the agent's credential file read-only yourself via the `docker.run` list of `~/.goga/config.yml`, or pass its API-key env var with `-e`, so the agent executing the plan runs with your live credentials (see [Credentials in the container](https://qarium.github.io/goga/features/pipelines/runtime/#credentials)).

Customize the run with the usual flags:

```bash
goga build plan.md --update               # refresh the image first (build from config dockerfile, else pull)
goga build plan.md --clean                # wipe persistent loop state for a fresh run
goga build plan.md -e ENV_VAR=value       # forward an extra env var into the container
goga build plan.md --skip-review          # run tasks only, skip the review phase
```

The build configuration in `.goga/config.yml` is two-part: the `build` root carries the tasks-pass settings (`agent`, `env`, iteration and session knobs), and its `review` sub-block carries the review-pass settings. A run with review on is always two passes — a tasks pass on the root agent's wrapper, then a review pass on the review agent's wrapper (`review.agent` inherits `build.agent` when unset); `--skip-review` or `review.skip: true` collapses the cycle to the tasks pass alone, and a failed tasks pass skips the review. The review pass is configured through the sub-block:

- Hand review to a different agent (`review.agent: codex` runs the review pass on the codex wrapper; unset inherits `build.agent`);
- Skip it by default (`review.skip: true` — `--no-skip-review` forces the full cycle);
- Select the reviewer composition (`review.roles: [quality, testing]`);
- Layer environment variables onto the review pass alone (`review.env: {ANTHROPIC_MODEL: reviewer}` — the variables overlay the container environment for the review subprocess only; the tasks pass never sees them, the review env never inherits the root env, and the values never reach logs or dry-run output);
- Bound the review diff to an explicit base (`review.base_ref: origin/main` — a branch name or commit hash that overrides ralphex's default-branch detection; `--base-ref` on the command line wins);
- Pick the review strategy (`review.strategy: full | medium | short`, default `medium` — `medium` disables the external reviewer; `full` keeps it; `short` runs the external review alone, on the additional agent's wrapper);
- Set a finalize prompt (`review.finalize: |` — a user-authored final review prompt materialized into ralphex's finalize step);
- Stop the external review after N unchanged rounds (`review.additional.patience: 3`, or `--review-patience`).

Before the first pass a validation gate runs: tools subscribed to `build/validate_build` read the resolved run facts and may veto the run (see [Tools](#tools) below). After a successful run the plan file itself moves to `completed/` inside its own topic directory (`.goga/history/<year>/<topic>/completed/`).

A running build executes inside a Docker container, where its run-state and logs are written to a persistent host directory and survive across runs of the same project on the same branch — so an interrupted build can be resumed. Pass `--clean` (or `-c`) to wipe that state before launch for a fresh run. After the build, test the implementation manually.

See [`goga build`](https://qarium.github.io/goga/features/build/cli/) for the full CLI reference, configuration, and exit codes.

## Tools

A **tool** is a pluggable capability package. Any open-source tool or in-house methodology is packaged as a Python package under the `goga_tool_` prefix and becomes part of the goga ecosystem: its skills land in a shared catalog at `~/.goga/skills/`, its pipeline-files install at `~/.goga/pipelines/` with a namespace prefix, and everything lives side by side, addressed uniformly.

### Installing a tool

Tools are distributed as Python packages under the `goga-tool-` prefix. `goga install` targets the running interpreter's pip directly and re-syncs every already-connected agent after a successful pip — the new tool's skills and pipelines appear in `~/.goga/` and in each agent's symlink tree immediately:

```bash
# Install one tool, latest version
goga install <tool-name>

# Install a pinned or ranged version (four-form grammar)
goga install <tool-name> --version 1.0.x

# Install every tool declared under tools: in .goga/config.yml in one pip call
goga install

# Install a tool from a local source directory (no PyPI lookup)
goga install --local <path>

# Same, naming the tool whose post-install hook runs
goga install --local <path>:<tool-name>
```

After a successful pip, `goga install` runs each freshly installed tool's optional post-install hook (a callable `install` in its facade — skipped quietly when absent), then re-syncs every already-connected agent automatically. Connect a new agent at any time:

```bash
goga connect <agent>
```

Pass `goga install --no-connect` to opt out of the post-install agent re-sync (CI/Docker escape-hatch; the post-install hooks still run). Pass `goga install --sudo` for system-Python installs requiring root.

See [`goga install`](https://qarium.github.io/goga/features/install/cli/) for the full version-grammar rules and single/bulk/empty/local semantics.

### Removing a tool

`goga uninstall` removes exactly one tool package from the running interpreter's pip. It asks for confirmation first — Enter removes (the default is Y), `n` cancels:

```bash
# Remove one tool (interactive confirmation, Enter = yes)
goga uninstall <tool-name>

# Skip the confirmation — the scripted/CI form
goga uninstall <tool-name> --yes
goga uninstall <tool-name> -y

# Remove from a system-Python install requiring root
goga uninstall <tool-name> --sudo

# Remove and re-sync another user's goga installation
goga uninstall <tool-name> --user alice
```

After a successful pip uninstall, every connected agent is re-synced: the removed tool's skills and pipelines disappear from `~/.goga/` and from each agent's symlink tree. A tool removed by hand with plain pip leaves those artifacts behind until the next re-sync.

See [`goga uninstall`](https://qarium.github.io/goga/features/install/uninstall/) for the full confirmation, sudo/user, and exit-code semantics.

### Using a tool

**Via CLI:**

```bash
goga tool <name> [args...]
```

**Via agent skill:**

Invoke the `/goga:tool <name>` command (or `goga-tool` skill) in your agent session. The slash-command form works in `claude`, `opencode`, `qwen`; in Codex and cursor, invoke the skill directly — `goga-tool` (Codex: `$goga-tool`).

### Built-in tools

The following tools ship with goga out of the box — no separate install required. They are registered automatically once goga is installed and `goga connect` has been run.

| Tool | Description                                                                                             |
|---|---------------------------------------------------------------------------------------------------------|
| **viewer** | Interactive dependency graph viewer for CODEMANIFEST cells                                              |
| **mkdocs** | Generate and maintain MkDocs documentation from CODEMANIFEST files                                      |
| **scriba** | The writer — translates texts between languages and reviews texts against prompt-engineering principles |

### Packaging your own tool

Minimal layout, illustrated by a tool named `acme` that ships four subcommands — `explore`, `propose`, `apply`, `archive` — and one pipeline-file:

```
goga_tool_acme/
├── __init__.py            # main(argv: list[str]) — CLI entry; optional install()/register_hooks()
├── skills/
│   ├── acme/
│   │   └── SKILL.md       # goga-tool-acme — the entry point
│   ├── acme-explore/
│   │   └── SKILL.md       # goga-tool-acme-explore
│   ├── acme-propose/
│   │   └── SKILL.md       # goga-tool-acme-propose
│   ├── acme-apply/
│   │   └── SKILL.md       # goga-tool-acme-apply
│   └── acme-archive/
│       └── SKILL.md       # goga-tool-acme-archive
└── pipelines/
    └── spec.yml           # → ~/.goga/pipelines/acme:spec.yml
```

A valid tool **must**:

- Be named with the `goga_tool_` prefix (PyPI publication under `goga-tool-`)
- Contain the entry-point skill `skills/<tool-name>/SKILL.md` — `goga connect` skips the whole package with a warning when it is missing (every skill directory carries a `SKILL.md`)
- Expose a `main(argv: list[str])` function for CLI execution
- A `pipelines/` directory is **optional**; when present, its flat `*.yml` files are copied into `~/.goga/pipelines/` at `goga connect` time, namespaced as `<tool>:<name>.yml`

A tool **may** additionally expose an `install(user: str | None = None)` callable in its facade package: `goga install` calls it after a successful pip, passing the initiating user (`SUDO_USER` when goga itself runs under sudo, else the current OS user) only when the parameter is declared keyword-capable. A missing or non-callable `install` is skipped quietly.

A tool **may** also expose a `register_hooks(hooks)` callable to extend goga domains with its own hooks. Today the hook zones are:

- **statuses** — the topic status scale registration (`register_statuses`);
- **onboarding** — the onboarding session (`declare_session`/`amend_config`, reached via `goga init -t <tool>`);
- **topics** — the nine topic-lifecycle checkpoints: two content amendments and seven notifications (see [Topics — Hooks](https://qarium.github.io/goga/features/topics/hooks/));
- **pipeline** — the three checkpoints: the workflow amendment `amend_workflow` and the two run notifications `run_created`/`run_completed` (see [Pipelines — Hooks](https://qarium.github.io/goga/features/pipelines/hooks/));
- **build** — the five checkpoints: the validation gate `validate_build`, delivered before the first pass with the resolved run facts, plus the four run notifications `build_started`, `pass_started`, `pass_completed`, `build_completed` (see [Build — Hooks](https://qarium.github.io/goga/features/build/hooks/));
- **config** — the config amendment checkpoint `config/amend_config`, delivered at the project-config load moment of every host-side config-consuming command (`pipeline`, `lint`, `contract`, `install` bulk, `config`, `build`, `topics`, `usages status/sync`) and delivered a second time in-container by the run form of `goga pipeline` and by `goga build` — the in-container delivery feeds the run parameters (`pipeline.agent`/`pipeline.env`, `build.*`) and fails the run cleanly (exit 1) on a hard hook failure (see [Configuration — Hooks](https://qarium.github.io/goga/configuration/hooks/));
- **schema** — the cell-amendment checkpoint `schema/amend_cell`, delivered at the generation moment of the project map (`goga schema`), and the validation gate `schema/validate_schema`, an observe-and-veto pass over the final assembled tree delivered after the tools overlay and before serialization (see [Schema — Hooks](https://qarium.github.io/goga/features/schema/hooks/));
- **contract** — the contract-amendment checkpoint `contract/amend_contract`, delivered at the comparison moment of every requested cell (`goga contract` — tools read the comparison facts of each cell and contribute per-type facts onto the `tools` area of the JSON output; see [Contract — Hooks](https://qarium.github.io/goga/features/contract/hooks/));
- **usages** — the four run-level moments `usages/sync_started`, `usages/sync_completed`, `usages/status_started`, `usages/status_completed` — all soft notifications wrapping `goga usages sync` and `goga usages status` (see [Usages — Hooks](https://qarium.github.io/goga/features/usages/hooks/)).

goga calls `register_hooks` when a command first reaches a hook checkpoint of the run, or when you inspect the registry with `goga hooks`; commands that use no hooks never call it:

```python
def register_hooks(hooks):
    hooks.subscribe("statuses", "register_statuses", "published", register_published)


def register_published(context):
    context.register("published", "mkdocs/published.md", after="planned")
```

The hook receives the delivered status registry through `context` — read and call freely, attribute assignment is blocked. The name is shown qualified as `<tool>.<name>` (here `mkdocs.published`); the tool identity is the package name with the `goga_tool_` prefix dropped and underscores turned into hyphens, so `goga_tool_hello_world` registers `hello-world.*`. The filepath is relative to the topic directory (nested paths allowed), and `before=`/`after=` anchor the entry to an existing scale entry — at least one anchor is required, both define a range. Built-in entries are immutable. A bad registration — an unknown anchor, an invalid range, or a crashed hook — is skipped with a warning on stderr and never aborts the command; only a package that fails to import is fatal. That skip-with-a-warning rule covers the **soft** actions; the platform's **hard** actions are `pipeline/amend_workflow`, `build/validate_build`, `config/amend_config`, `schema/amend_cell`, `schema/validate_schema`, and `contract/amend_contract` — a hook of the first that raises (or contributes a malformed document) aborts `goga pipeline` before any launch with a clean error naming the hook, the tool, and the action; the build gate instead lets every subscribed tool's hooks run to completion, collects their `context.veto(reason)` calls (a raising hook counts as its tool's veto, with the crash reason), and merges all vetoes into one error that stops `goga build` before any pass; the config amendment stops the command at the first failing tool with the same clean error (a structurally malformed contribution — an unknown path, a non-leaf address, a wrong-typed value — is treated identically, and the tool's whole contribution is discarded); the schema cell amendment stops `goga schema` at the first failing tool the same way — a crashed hook or a contribution not representable in the node's JSON map — its error naming the tool, the action, and the failing cell path, with no partial map printed; the schema validation gate runs like the build gate — every subscribed tool's hooks run to completion, one veto per tool (`context.veto(reason)`; a crash counts as that tool's veto), merged into one error that stops `goga schema` before any output, nothing on stdout; the contract amendment stops `goga contract` at the first failing tool the same way — a crashed hook, a structurally malformed contribution, or a contribution addressing a type the cell does not declare — with the same clean error naming the hook, the tool, the action, and the failing cell path, and no partial JSON printed. Run [`goga hooks`](https://qarium.github.io/goga/features/hooks/cli/) to inspect what is registered. The removed `register_topic_statuses(statuses)` callback is no longer called — a package still carrying it loses its statuses silently after the update.

After publication, install into any project:

```bash
goga install acme
goga pipeline acme:spec            # namespaced pipeline from the tool
```

The subcommands become ordinary agent skills — `goga-tool-acme-explore`, `goga-tool-acme-propose`, `goga-tool-acme-apply`, `goga-tool-acme-archive` — that can be invoked directly (`/goga:tool acme explore`, `goga-tool-acme-explore`, or `$goga-tool-acme-explore` in Codex) or merged into any stage of any pipeline via `skills:` in a workflow-file. The `acme` cycle `explore → propose → apply → archive` can be run end-to-end through `acme:spec`, woven stage-by-stage into the SDD cycle, or composed into a custom pipeline where `goga-tool-acme-propose` runs next to `goga-prototype`.

The entry point may optionally declare a keyword-capable `ast` parameter to receive the project AST (loaded lazily from the current project root, only when declared). It may likewise declare a keyword-capable `config` parameter to receive the tool's raw YAML config from `.goga/tools/<tool>/config.yml` (an absent file delivers `None`). A tool that declares neither keeps the minimal `main(argv)` form and the AST is never built. See [`goga tool`](https://qarium.github.io/goga/features/tools/cli/) for the entry-point forms and opt-in rules.

### Skill naming

When `goga connect` installs a tool, the prefix `goga-tool-<tool-name>-` is added to every skill and the result lives centrally under `~/.goga/skills/`:

| In package (`skills/`)       | After `goga connect` (`~/.goga/skills/`) |
|------------------------------|------------------------------------------|
| `mkdocs/SKILL.md`            | `goga-tool-mkdocs`                       |
| `mkdocs-discovery/SKILL.md`  | `goga-tool-mkdocs-discovery`             |
| `mkdocs-writer/SKILL.md`     | `goga-tool-mkdocs-writer`                |

Rules:

- Use lowercase with hyphens as separators
- The entry-point skill directory is named exactly `<tool-name>` — it becomes the skill invoked by `/goga:tool <name>` (or `goga-tool` / `$goga-tool` in agents without slash-command support). It is required: a package without `skills/<tool-name>/SKILL.md` is skipped by `goga connect` with a warning.
- Name sub-skills descriptively using the `<tool-name>-<purpose>` pattern (e.g., `mkdocs-discovery`, `mkdocs-validator`)

### Pipeline namespacing

Tool pipelines are namespaced on install. A file `<name>.yml` in a tool's `pipelines/` directory is copied into `~/.goga/pipelines/` **as `<tool>:<name>.yml`**, where `<tool>` is the package name with the `goga_tool_` prefix dropped and underscores normalized to hyphens (`goga_tool_hello_world` → `hello-world`):

| Source                                    | Destination in `~/.goga/pipelines/`  | Addressable as                |
|-------------------------------------------|--------------------------------------|-------------------------------|
| Internal goga source (`goga/assets/pipelines/`) | `development.yml` (un-prefixed) | `goga pipeline development`   |
| Tool package `goga_tool_acme/pipelines/deploy.yml` | `acme:deploy.yml`             | `goga pipeline acme:deploy`   |

Namespacing structurally prevents collisions — between a tool pipeline and an internal-source pipeline, and between two tools shipping the same name. See [Shipped Pipelines](https://qarium.github.io/goga/features/pipelines/shipped/) for the full installation algorithm.

Read the full Tools model in the [Tools](https://qarium.github.io/goga/features/tools/) section of the docs.

## SDD — the reference cycle

Out of the box, goga ships a full Specification-Driven Development (SDD) cycle. This is the three pillars in action: a pipeline-file describes the stages, tools supply skills, and CODEMANIFEST is the contract language used inside the stages. Use the cycle as is, extend it through workflows, or replace it with your own methodology built from tools and pipelines.

### Contracts as the source of truth

A **cell** is a directory that encapsulates a distinct responsibility domain with a well-defined API boundary. Each cell contains a `CODEMANIFEST` file describing its contract and an optional `.usages/` directory with documentation for API consumers.

```
cell/
├── CODEMANIFEST       # YAML DSL describing the API contract
└── .usages/*.md       # Practices for working with the cell
```

The rule of thumb is **one responsibility zone — one cell**. A new cell is born when logic can be decoupled, owns distinct data models, must be reused, or can be stated in a single phrase without "and".

#### Sharing specs across projects

Cell `.usages/` practices can be shared through git: declare a dependency in `.goga/config.yml` and run `goga usages sync` — usage files from the source repository sync into `.goga/usages/<group>/<dep>/`, ready to be referenced by `Usages` in any CODEMANIFEST.

#### Anatomy of a contract

A `CODEMANIFEST` consists of three sections separated by `---`:

- **Header** — `Imports` (types and usages from other cells), `Usages` (named practices), `Annotations` (global directives)
- **Body** — entities and routines that form the cell's public API
- **Footer** — `Author`, `CreatedAt`, `Description`

Cells expose three kinds of types:

- **Entity types** — objects with state and behavior (services, configurations, data models): properties + methods
- **Routine types** — single operations (transformers, factories, validators, parsers): no state
- **Embedded types** — re-exports of imported types: `->ExternalService`

Specialization is expressed with the `::` mutation syntax. The DSL stays language-agnostic — `BaseEntity::ExtendedEntity` may be realized through inheritance, composition, an adapter, or an interface implementation in the target language.

#### Example

```yaml
Imports:
  - Types:
      - AnotherCellType
    From: path/to/another_cell

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

Annotations: |
  Use `conventions` when writing code.

---

"ParseInput(input: string) -> data:List<byte>":
  location: parser.py
  annotations: |
    Parses raw input into a byte buffer.
  
    `input`: raw request payload

"HTTPServer(name: String)":
  location: server.py
  properties:
    "host -> String": |
      Bind address for incoming connections.
  methods:
    "handleRequest(req: Request) -> resp:Response": |
      Dispatches a single HTTP request.

      Algorithm:
      1. Parse input from `req` with `ParseInput`
      2. Filter result by some logic
      3. Save filtered result in `resp`
      4. Return `resp` object

---

Author: Goga
CreatedAt: 01/01/26
Description: |
  HTTP entry point cell.
```

### Extending the cycle

The SDD cycle is not monolithic — every part of it is extensible through the same workflow mechanisms described in the [Pipelines](#workflows--configure-and-extend-a-pipeline) section, applied to the shipped `development` pipeline.

**Add an external skill to a stage.** `prototype-architecture` gains an extra skill from the `acme` tool alongside `goga-prototype`:

```yaml
# .goga/workflows/development.yml
stages:
  prototype-architecture:
    skills: [goga-tool-acme-explore]
```

**Swap an SDD stage for an external equivalent.** On `architecture-review`, switch to `codex` and run `goga-tool-acme-explore` against the spec; on `apply-architecture`, loop twice and pair `goga-apply` with `goga-tool-acme-apply`:

```yaml
stages:
  architecture-review:
    agent: codex
    skills: [goga-tool-acme-explore]
  apply-architecture:
    loop: 2
    skills: [goga-tool-acme-apply]
```

**Insert new stages from a tool's arsenal.** Between `plan-review` and `commit-changes`, run `goga-tool-acme-explore` to walk the spec; after `accept-result`, run `goga-tool-acme-archive` to archive the delivered spec snapshot:

```yaml
extend:
  spec-explore:
    after: [plan-review]
    before: [commit-changes]
    title: Spec exploration
    skills: [goga-tool-acme-explore]
    prompt: |
      Walk the current spec before architecture work begins.
  spec-archive:
    after: [accept-result]
    title: Archive spec
    skills: [goga-tool-acme-archive]
    prompt: |
      Archive the delivered spec snapshot.
```

**Run a stage for two passes.** `plan-review` with `loop: 2` runs two sequential passes with increasing depth:

```yaml
stages:
  plan-review:
    loop: 2
```

**Finish autonomously.** `accept-result` with `approve: auto` suppresses the user prompt and self-approves:

```yaml
stages:
  accept-result:
    approve: auto
```

These are not special "SDD extension points" — they are exactly the same workflow mechanisms from the Pipelines section, applied to the SDD cycle. Combining tools and workflows, SDD can be compressed to `specify → accept` for prototypes or expanded with threat-modelling, security review, and compliance gates for production. Read the full functional model in the [Workflows](https://qarium.github.io/goga/features/pipelines/workflows/) section of the docs.

## Topics

Work is organized as **topics** — one directory per piece of work under `.goga/history/<year>/<topic>/`, each usually living on its own git branch. The `goga topics` command group manages them:

```bash
goga topics board               # the board: one entry per topic of the year with its own branch
goga topics board --remote      # same board over remote-tracking refs
goga topics board --info        # the board with the todo column (the todo summary of todo.md)
goga topics board --per-host    # the audit view: one row per topic and hosting branch
goga topics board --json        # the machine-readable board (pretty-printed JSON, either view)
goga topics board --host feat/x --host main   # keep only the topics hosted by the named branches
goga topics board --topic feat-x --topic feat-y   # keep only the named topics (repeatable, composes with --host)
goga topics create feat/x --from-current    # fresh work off the current HEAD: the branch verbatim + its topic committed, you stay on your branch
goga topics create feat/x --from-current -t "Payment retry"   # same; the todo becomes the branch's todo.md commit (status: todo)
printf 'Payment retry.\n' | goga topics create feat/x --from-current --todo   # same; the piped stdin is the todo (value-less --todo), no publication ask
goga topics create feat/x --from-current -s    # same, but switch to the fresh branch; on a terminal the todo entry opens in your `$EDITOR`
goga topics create feat/x --from-current -p -t "Payment retry"   # same as the default, plus pushed to origin
goga topics switch feat-x       # onto the branch hosting that work (branch, slug, or prefix)
goga topics switch feat-x --todo    # same, then edit the topic's todo.md in your `$EDITOR`
goga topics update feat-x       # bring the topic up to its base (merge/rebase per topics.update.strategy), checkout-free
goga topics update --publish    # update the current topic, then push the refreshed branch (rebase pushes under a lease)
goga topics publish feat-x      # deliver an existing topic branch to origin (pushed / up-to-date / remote-ahead; a diverged twin is a clean error)
goga topics propagate feat-x    # deliver the finished topic into its base and push it — one confirmation (--yes skips)
goga topics delete feat-x       # delete the branch, its origin twin, and the directory
goga topics clear               # delete every merged topic of the year (base: --base-ref or topics.base_ref), one confirmation
goga topics --year 2025 board   # the board of an explicit year
```

Every `create` needs a base: `--base-ref`, or `topics.base_ref` in `.goga/config.yml`, or the current HEAD under `--from-current`. The default creation quarantines the topic into the branch — one commit carrying the topic's `todo.md` on top of the base — while you stay on your branch; the todo is required there. `-t`/`--todo` carries three states: a value is the todo itself, the value-less form takes it from the piped stdin (read fully once, strictly UTF-8, verbatim; piped content without the declaration is a clean error), and with nothing given a terminal opens the external editor for the todo. Once a todo is resolved the command asks on a terminal whether to publish — never when the todo came from the pipe; without a terminal the no-switch creation is a clean error while `-s` succeeds with no todo. `-s`/`--switch` checks out the fresh branch instead — the topic directory and `todo.md` land in the working copy uncommitted, and the todo is optional. `--publish`/`-p` is the fast mode: it builds the branch off the resolved base with a single `todo.md` commit and pushes it to `origin` without switching — your working copy, index, and HEAD stay untouched, and a failed push rolls the branch back. See [`goga topics`](https://qarium.github.io/goga/features/topics/cli/).

The exchange pair works against the same `topics.base_ref` base (`--base-ref` beats it). `goga topics update` brings a topic up to its base under `topics.update.strategy` (`merge`, `rebase`, `ff-else-merge`, `ff-else-rebase`) — another topic updates fully checkout-free while you stay on your branch, the current one updates in place behind a read-only pre-flight, and every conflict is a clean error pointing at manual git before anything mutates. `goga topics publish` delivers an existing topic branch to origin as an operation of its own — an omitted identifier addresses the current topic, no confirmation, no force or lease ever, no configuration keys; one targeted fetch of the branch's own origin twin, then one of three success kinds (`pushed` — the twin is created or fast-forwarded from behind, `up-to-date`, `remote-ahead`), one stdout line naming the kind, and exit 0 on all three (a diverged twin — neither contains the other — is a clean error naming both tips). `goga topics propagate` delivers a finished topic into its base (`topics.propagate.strategy`: `merge`, `ff`, `squash`) and pushes it — the push is inherent — after exactly one confirmation naming the topic, the base, and the push; a base the remote moved concurrently gets one retry cycle, and a base that already carries the topic is the idempotent `nothing-to-do` success. The exchange pair needs git >= 2.40.

A `clear` takes the same `topics.base_ref` base — `--base-ref` beats it, and there is no current-HEAD rung — and removes every own-branched topic of the year the base's tree already carries (the merged work), each with its branch, its `origin` twin, and its directory; a topic without its own branch is silently skipped — it is history. An empty scope is one line and exit 0.

The board is a four-column table — topic, branch, hosts, statuses, plus the todo and delivery columns under `--info` (the delivery cell shows the topic's divergence against the configured `topics.base_ref`: `base`, `up-to-date`, `propagated`, or `need-update`) — one entry per topic that still has its own branch, with `*` marking the current branch and the hosts column listing every branch carrying the topic's history (a local branch absorbing its remote twin). Each topic carries its **maximal statuses** in scale order: `empty → todo → defined → discovered → backlog → prototyped → designed → planned → done`, deepening as `todo.md`, `prd.md`, `adr.md`, `task.md`, `arch.md`, `design.md`, `plan.md`, and `completed/plan.md` land. A topic can carry several statuses at once (`goga history status` prints them; `-s` filters by any of them).

Topics no branch hosts anymore are orphans — [`goga history`](https://qarium.github.io/goga/features/history/cli/) `prune --dry-run` lists the orphans of a year, and `goga history -y <year> prune` deletes them (the year is the group's `-y`/`--year` option, given once before the subcommand; irreversibly: the history tree is not in git).

To resume work inside a pipeline, pass the identifier to the run — `goga pipeline development -t feat/x` switches to the hosting branch first (creating a local branch from its remote-tracking ref when needed) and is an idempotent no-op when you are already on it; adding `--todo` opens the topic's `todo.md` in your editor after the switch. Fresh work is better started with `goga topics create` — it takes an explicit base, todo, and publication; a pipeline `-t` creates from the current HEAD when nothing hosts the identifier.

## Documentation

Full documentation is available at [qarium.github.io/goga](https://qarium.github.io/goga/).

## Contributing

After cloning, enable the local git hooks once:

```bash
make install-hooks
```

This installs two-layer protection against `Co-Authored-By:` trailers (project policy: no co-authorship in git history):

- **commit-msg** — blocks the commit at creation time.
- **pre-push** — blocks the push if any new commit being pushed contains the trailer (catches cases where the commit-msg hook was bypassed with `--no-verify` or not installed).

Bypass in rare intentional cases with `git commit --no-verify` / `git push --no-verify`.
