---
since: 1.1.1
---
# Architecture Diagrams
Detailed flow diagrams for individual gitaiflow subsystems. For the top-level pipeline, see [`gitaiflow.md`](gitaiflow.md).
## 1. Execution mode routing
```mermaid
flowchart TD
A["gitaiflow <flags>"] --> B{"Which mode flag
is present?"}
B -->|"--list-models"| C["Model Catalog Mode
OpenRouter /models"]
B -->|"--usage / --telemetry"| D["Local Reporting Mode
usage.jsonl / consent file"]
B -->|"--changelog"| E["Changelog Mode
no AI call"]
B -->|"none of the above"| F["Normal Summary Mode
calls configured AI provider"]
C --> C1["Query OpenRouter catalog
no AI_PROVIDER required"]
D --> D1["Read/write local files only
exit immediately"]
E --> E1["Read change-summary JSON
or fall back to git log"]
F --> F1["Fail fast if no AI provider
is configured"]
F1 --> F2["Full pipeline
diff → prompt → AI → JSON"]
classDef entry fill:#e6f1fb,stroke:#2474b5,stroke-width:2px,color:#174d7a
classDef decision fill:#fff2d9,stroke:#d89b18,stroke-width:2px,color:#76520b
classDef mode fill:#e5f6f1,stroke:#159a7a,stroke-width:2px,color:#075d4b
classDef output fill:#eeeaff,stroke:#7655c7,stroke-width:2px,color:#4a3485
class A entry
class B decision
class C,D,E,F mode
class C1,D1,E1,F1,F2 output
```
## 2. Normal summary pipeline (detail)
```mermaid
flowchart LR
A["Git repository"] --> B["DiffGenerationService
root, base ref, changed files"]
B --> C["Exclusions +
sensitive-line redaction"]
C --> D["ArtifactManager
change-summary/<date>/diff/"]
D --> E{"--no-chunk?"}
E -->|No, default| F["Group changed files
by top-level subdirectory"]
E -->|Yes| G["Single group:
entire diff"]
F --> H["One PromptBuilder call
per group"]
G --> H
H --> I["AIClient
OpenAI-compatible request"]
I --> J["commit_parser
TITLE: / BODY:"]
J --> K["json_writer
canonical JSON"]
K -->|"--markdown"| L["Derived Markdown view"]
I --> M["usage_log
local + optional telemetry"]
classDef local fill:#e8f7f1,stroke:#2b9a78,stroke-width:2px,color:#174d3d
classDef decision fill:#fff2d9,stroke:#d89b18,stroke-width:2px,color:#76520b
classDef external fill:#eaf0ff,stroke:#5b6fc8,stroke-width:2px,color:#293665
classDef output fill:#f0eaff,stroke:#7957c7,stroke-width:2px,color:#382568
class A,B,C,D local
class E decision
class F,G,H,J,K,M local
class I external
class L output
```
## 3. Telemetry consent decision
```mermaid
flowchart TD
A["gitaiflow run reaches
the telemetry decision point"] --> B{"GITAIFLOW_TELEMETRY
env var set?"}
B -->|"true / false"| C["Use env var value
this process only,
saved consent unchanged"]
B -->|"unset"| D{"Saved consent exists at
~/.gitaiflow_telemetry_consent?"}
D -->|Yes| E["Use saved decision"]
D -->|No| F{"Interactive terminal?"}
F -->|Yes| G["Prompt:
Enable anonymous usage
telemetry? [y/N]"]
F -->|No — CI, pipe, redirect| H["Default to OFF
no prompt shown"]
G --> I{"Answer?"}
I -->|"y"| J["Save 'yes' + version + timestamp
to consent file"]
I -->|"N / Enter / Ctrl-C / EOF"| K["Save 'no' + version + timestamp
to consent file"]
C --> L{"Telemetry active
for this run?"}
E --> L
H --> L
J --> L
K --> L
L -->|Yes| M["Send documented payload
version, provider, model, counts,
duration, OS, success — no code/paths"]
L -->|No| N["No transmission"]
classDef entry fill:#e6f1fb,stroke:#2474b5,stroke-width:2px,color:#174d7a
classDef decision fill:#fff2d9,stroke:#d89b18,stroke-width:2px,color:#76520b
classDef local fill:#e8f7f1,stroke:#2b9a78,stroke-width:2px,color:#174d3d
classDef external fill:#eeeaff,stroke:#7957c7,stroke-width:2px,color:#382568
class A entry
class B,D,F,I,L decision
class C,E,H,J,K,N local
class G local
class M external
```
`GITAIFLOW_TELEMETRY` overriding the saved decision for "this process only" is what lets CI flip telemetry per-job without disturbing a developer's durable local answer — see [`../user-guide/telemetry.md`](../user-guide/telemetry.md).
## 4. Changelog generation
```mermaid
flowchart TD
A["gitaiflow --changelog
--since ... [--until ...]"] --> B["Resolve remote/base-branch
same rule as normal summary"]
B --> C["Parse --since/--until
exact date or relative expression"]
C --> D{"Range valid?
not future, not entirely
pre-history"}
D -->|No| E["ChangelogRangeError
rejected upfront, nothing written"]
D -->|Yes| F["Look for existing
change-summary JSON artifacts
in range, matching base"]
F --> G{"Artifacts found?"}
G -->|Yes| H["Use JSON artifacts
newest wins per overlapping file"]
G -->|No| I["Fall back to git log
on resolved base ref"]
H --> J["Bucket by
conventional-commit type"]
I --> J
J --> K["Render populated sections only"]
K --> L{"Existing CHANGELOG.md
has same version heading?"}
L -->|Yes| M["Replace that version's block"]
L -->|No| N["Prepend new section
before latest existing release"]
M --> O["CHANGELOG.md"]
N --> O
classDef entry fill:#e6f1fb,stroke:#2474b5,stroke-width:2px,color:#174d7a
classDef decision fill:#fff2d9,stroke:#d89b18,stroke-width:2px,color:#76520b
classDef local fill:#e8f7f1,stroke:#2b9a78,stroke-width:2px,color:#174d3d
classDef error fill:#fff0f0,stroke:#d64545,stroke-width:2px,color:#5c2020
classDef output fill:#f0eaff,stroke:#7957c7,stroke-width:2px,color:#382568
class A entry
class B,C local
class D,G,L decision
class F,H,I,J,K,M,N local
class E error
class O output
```
Changelog generation never calls an AI provider and never records a normal-run usage or telemetry event — only Git and local artifact reads/writes are involved.
## 5. Diff caching / regeneration skip
```text
DiffGenerationService generates diff for a group
│
▼
diff content hash compared against
previously summarized diffs (any prior day)
│
┌────┴────┐
│ │
match no match
│ │
▼ ▼
reuse call AI provider,
earlier write new summary
summary for this diff
(no AI call)
```
`--regenerate-summary` bypasses this comparison unconditionally, forcing a fresh AI call for every group regardless of a matching prior diff.
## 6. Provider boundary
```text
AIClient
│
OpenAI-compatible chat/completions
│
┌────────────┼─────────────────────────┐
│ │ │
Gemini OpenAI custom endpoint
(OpenAI-compat /v1 (OpenRouter, Grok,
endpoint) DeepSeek, vLLM,
│ LM Studio, ...)
│ │
▼ ▼
cloud provider cloud or self-hosted,
receives prompt receives prompt + diff
+ diff content content
│
│ ┌───────────────┐
└────────────│ Ollama │◀── request stays on
│ (local model) │ the local machine
└───────────────┘
```
For local Ollama usage, the AI request never leaves the machine. For every cloud provider, the provider receives the filtered/redacted prompt and diff content required to generate the summary — see [`security-and-privacy.md`](security-and-privacy.md) for the full data-flow boundary.