Architecture Diagrams
Detailed flow diagrams for individual gitaiflow subsystems. For the top-level pipeline, see gitaiflow.md.
On this page ▾
1. Execution mode routing
flowchart TD
A["gitaiflow <flags>"] --> B{"Which mode flag<br/>is present?"}
B -->|"--list-models"| C["Model Catalog Mode<br/><small>OpenRouter /models</small>"]
B -->|"--usage / --telemetry"| D["Local Reporting Mode<br/><small>usage.jsonl / consent file</small>"]
B -->|"--changelog"| E["Changelog Mode<br/><small>no AI call</small>"]
B -->|"none of the above"| F["Normal Summary Mode<br/><small>calls configured AI provider</small>"]
C --> C1["Query OpenRouter catalog<br/><small>no AI_PROVIDER required</small>"]
D --> D1["Read/write local files only<br/><small>exit immediately</small>"]
E --> E1["Read change-summary JSON<br/>or fall back to git log"]
F --> F1["Fail fast if no AI provider<br/>is configured"]
F1 --> F2["Full pipeline<br/><small>diff → prompt → AI → JSON</small>"]
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 output2. Normal summary pipeline (detail)
flowchart LR
A["Git repository"] --> B["DiffGenerationService<br/><small>root, base ref, changed files</small>"]
B --> C["Exclusions +<br/>sensitive-line redaction"]
C --> D["ArtifactManager<br/><small>change-summary/<date>/diff/</small>"]
D --> E{"--no-chunk?"}
E -->|No, default| F["Group changed files<br/>by top-level subdirectory"]
E -->|Yes| G["Single group:<br/>entire diff"]
F --> H["One PromptBuilder call<br/>per group"]
G --> H
H --> I["AIClient<br/><small>OpenAI-compatible request</small>"]
I --> J["commit_parser<br/><small>TITLE: / BODY:</small>"]
J --> K["json_writer<br/><small>canonical JSON</small>"]
K -->|"--markdown"| L["Derived Markdown view"]
I --> M["usage_log<br/><small>local + optional telemetry</small>"]
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 output3. Telemetry consent decision
flowchart TD
A["gitaiflow run reaches<br/>the telemetry decision point"] --> B{"GITAIFLOW_TELEMETRY<br/>env var set?"}
B -->|"true / false"| C["Use env var value<br/><small>this process only,<br/>saved consent unchanged</small>"]
B -->|"unset"| D{"Saved consent exists at<br/>~/.gitaiflow_telemetry_consent?"}
D -->|Yes| E["Use saved decision"]
D -->|No| F{"Interactive terminal?"}
F -->|Yes| G["Prompt:<br/>Enable anonymous usage<br/>telemetry? [y/N]"]
F -->|No — CI, pipe, redirect| H["Default to OFF<br/><small>no prompt shown</small>"]
G --> I{"Answer?"}
I -->|"y"| J["Save 'yes' + version + timestamp<br/>to consent file"]
I -->|"N / Enter / Ctrl-C / EOF"| K["Save 'no' + version + timestamp<br/>to consent file"]
C --> L{"Telemetry active<br/>for this run?"}
E --> L
H --> L
J --> L
K --> L
L -->|Yes| M["Send documented payload<br/><small>version, provider, model, counts,<br/>duration, OS, success — no code/paths</small>"]
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 externalGITAIFLOW_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.
4. Changelog generation
flowchart TD
A["gitaiflow --changelog<br/>--since ... [--until ...]"] --> B["Resolve remote/base-branch<br/><small>same rule as normal summary</small>"]
B --> C["Parse --since/--until<br/><small>exact date or relative expression</small>"]
C --> D{"Range valid?<br/><small>not future, not entirely<br/>pre-history</small>"}
D -->|No| E["ChangelogRangeError<br/><small>rejected upfront, nothing written</small>"]
D -->|Yes| F["Look for existing<br/>change-summary JSON artifacts<br/>in range, matching base"]
F --> G{"Artifacts found?"}
G -->|Yes| H["Use JSON artifacts<br/><small>newest wins per overlapping file</small>"]
G -->|No| I["Fall back to git log<br/>on resolved base ref"]
H --> J["Bucket by<br/>conventional-commit type"]
I --> J
J --> K["Render populated sections only"]
K --> L{"Existing CHANGELOG.md<br/>has same version heading?"}
L -->|Yes| M["Replace that version's block"]
L -->|No| N["Prepend new section<br/>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 outputChangelog 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
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
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 for the full data-flow boundary.