--- 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.