|
| 1 | +# Architecture |
| 2 | + |
| 3 | +A quick overview: giv is a POSIX-compliant shell script suite whose main entrypoint (giv.sh) initializes environment and dispatches subcommands. It sources modular libraries for configuration, system utilities, argument parsing, Markdown handling, LLM integration, project metadata, history extraction, and subcommand implementations. Major workflows include commit summarization (via summarize\_commit), changelog generation (cmd\_changelog), release-notes and announcements (via cmd\_document), and a generic document driver. Data domains span Git metadata (commits, diffs, tags), project metadata (version files, project titles), AI prompt templates, and generated summaries. Caching under `.giv/cache` avoids redundant work. Below are the details. |
| 4 | + |
| 5 | +## Repository Structure |
| 6 | + |
| 7 | +### Script Entry Point |
| 8 | + |
| 9 | +The main script, **giv.sh**, locates the library, template, and docs directories, sources all helper modules, parses arguments, and dispatches to subcommands like `message`, `summary`, `changelog`, `release-notes`, `announcement`, `document`, and maintenance commands (`init`, `update`) ([giv.sh][1]). |
| 10 | + |
| 11 | +### Configuration Module |
| 12 | + |
| 13 | +**config.sh** exports globals for version (`__VERSION`), directory paths (`GIV_HOME`, `GIV_TMP_DIR`, `GIV_CACHE_DIR`), debugging flags, default Git revision/pathspec, AI model and API settings, project tokens, and default output filenames (`CHANGELOG.md`, etc.) ([config.sh][2]). |
| 14 | + |
| 15 | +### System Utilities |
| 16 | + |
| 17 | +**system.sh** provides logging functions (`print_debug`, `print_info`, etc.), temporary-dir management (`portable_mktemp_dir`, `remove_tmp_dir`), `.giv` directory initialization (`ensure_giv_dir_init`), and location helpers (`find_giv_dir`) ([system.sh][3]). |
| 18 | + |
| 19 | +### Argument Parsing |
| 20 | + |
| 21 | +**args.sh** defines `show_help` and `parse_args`, mapping CLI options to `GIV_*` variables, validating revisions/pathspecs, handling config files early, and configuring local vs remote AI modes ([args.sh][4]). |
| 22 | + |
| 23 | +### Markdown Handling |
| 24 | + |
| 25 | +**markdown.sh** implements `manage_section` for append/prepend/update of Markdown sections, `append_link` to add links, utilities for stripping and normalizing Markdown (`strip_markdown`, `normalize_blank_lines`), and Markdown viewing via `glow` ([markdown.sh][5]). |
| 26 | + |
| 27 | +### LLM Integration |
| 28 | + |
| 29 | +**llm.sh** handles JSON-escaping (`json_escape`), remote API calls (`generate_remote` via curl), local inference (`run_local` via Ollama), response parsing (`extract_content_from_response`), and high-level `generate_response`, along with prompt token replacement (`replace_tokens`), prompt building (`build_prompt`), and execution (`generate_from_prompt`) ([llm.sh][6]). |
| 30 | + |
| 31 | +### Project Metadata |
| 32 | + |
| 33 | +**project.sh** extracts project titles and version information from common project files like `package.json`, `pyproject.toml`, and `setup.py`. It also supports custom version file detection ([project.sh][7]). |
| 34 | + |
| 35 | +### History Extraction |
| 36 | + |
| 37 | +**history.sh** provides utilities for summarizing Git history, extracting TODO changes, and caching summaries ([history.sh][8]). |
| 38 | + |
| 39 | +### Subcommand Implementations |
| 40 | + |
| 41 | +**commands.sh** ties everything into user-facing commands: `cmd_message` for AI draft commit messages, `cmd_changelog` for changelog updates (using `manage_section`), `cmd_document` as a generic driver for release-notes, announcements, custom docs, and maintenance commands (`show_version`, `get_available_releases`, `run_update`) ([commands.sh][9]). |
| 42 | + |
| 43 | +## Data Domains |
| 44 | + |
| 45 | +1. **Git Data**: Commits, diffs, staged/unstaged changes, untracked files, commit dates, tags and ranges (handled by `build_diff`, `get_commit_date`, Git plumbing) ([history.sh][8]). |
| 46 | +2. **Project Metadata**: Version files (`package.json`, etc.), extracted versions (`get_version_info`), and project titles (`get_project_title`) ([project.sh][7]). |
| 47 | +3. **AI Prompt Templates**: Markdown templates stored under `templates/` (e.g. `summary_prompt.md`, `changelog_prompt.md`, `release_notes_prompt.md`, `announcement_prompt.md`) ([giv.sh][1]). |
| 48 | +4. **Generated Content**: Summary Markdown, commit messages, changelogs, release notes, announcements, managed under `.giv/cache` and output files in project root ([system.sh][3]) ([history.sh][8]). |
| 49 | +5. **Configuration & State**: Stored in `.giv/config`, `.giv/cache`, `.giv/.tmp`, and optionally `.giv/templates` (after `init`) ([system.sh][3]). |
| 50 | + |
| 51 | +## Workflows |
| 52 | + |
| 53 | +### Commit Summarization |
| 54 | + |
| 55 | +The `summarize_commit` function in **history.sh** orchestrates: |
| 56 | + |
| 57 | +1. Generating raw history with `build_history`. |
| 58 | +2. Finding version info via `get_version_info`. |
| 59 | +3. Building an AI prompt (`build_prompt` with `summary_prompt.md`). |
| 60 | +4. Generating the summary (`generate_response`). |
| 61 | + Caching ensures repeated calls skip regeneration ([history.sh][8], [llm.sh][6]). |
| 62 | + |
| 63 | +### Changelog Generation |
| 64 | + |
| 65 | +`cmd_changelog` in **commands.sh** follows: |
| 66 | + |
| 67 | +1. Summarize commits/ranges with `summarize_target`. |
| 68 | +2. Build the changelog prompt (`changelog_prompt.md`) via `build_prompt`. |
| 69 | +3. Generate content (`generate_from_prompt`). |
| 70 | +4. Update `CHANGELOG.md` using `manage_section` and append a “Managed by giv” link ([commands.sh][9]). |
| 71 | + |
| 72 | +### Release-Notes & Announcements |
| 73 | + |
| 74 | +Both use the generic `cmd_document` driver: |
| 75 | + |
| 76 | +1. Summarize history into temp file. |
| 77 | +2. Build prompt from `release_notes_prompt.md` or `announcement_prompt.md`. |
| 78 | +3. Call `generate_from_prompt` with tailored temperature and context window ([giv.sh][1]). |
| 79 | +4. Output to `RELEASE_NOTES.md` or `ANNOUNCEMENT.md`. |
| 80 | + |
| 81 | +### Generic Document Generation |
| 82 | + |
| 83 | +The `document` subcommand invokes `cmd_document` with a user-supplied `--prompt-file`, enabling arbitrary AI-driven reports over any revision/pathspec ([commands.sh][9]). |
| 84 | + |
| 85 | +## Architecture Diagrams |
| 86 | + |
| 87 | +### Sequence Diagram |
| 88 | + |
| 89 | +```mermaid |
| 90 | +sequenceDiagram |
| 91 | + participant User |
| 92 | + participant giv.sh |
| 93 | + participant Args as args.sh |
| 94 | + participant History as history.sh |
| 95 | + participant LLM as llm.sh |
| 96 | + participant Markdown as markdown.sh |
| 97 | + participant Output |
| 98 | +
|
| 99 | + User->>giv.sh: runs `giv changelog v1.2.0..HEAD` |
| 100 | + giv.sh->>Args: parse_args(...) |
| 101 | + Args-->>giv.sh: globals set |
| 102 | + giv.sh->>History: summarize_target(...) |
| 103 | + History-->>History: build_history(...) |
| 104 | + History->>LLM: build_prompt + generate_response |
| 105 | + LLM-->>History: AI summary |
| 106 | + History-->>giv.sh: summaries file |
| 107 | + giv.sh->>Markdown: manage_section(...) |
| 108 | + Markdown-->>giv.sh: updated Markdown |
| 109 | + giv.sh->>Output: write CHANGELOG.md |
| 110 | +``` |
| 111 | + |
| 112 | +### Class Diagram |
| 113 | + |
| 114 | +```mermaid |
| 115 | +classDiagram |
| 116 | + class giv.sh { |
| 117 | + +get_script_dir() |
| 118 | + +parse_args() |
| 119 | + +dispatch() |
| 120 | + } |
| 121 | + class config.sh { |
| 122 | + - export GIV_* |
| 123 | + } |
| 124 | + class system.sh { |
| 125 | + +print_debug() |
| 126 | + +portable_mktemp_dir() |
| 127 | + +ensure_giv_dir_init() |
| 128 | + } |
| 129 | + class args.sh { |
| 130 | + +parse_args() |
| 131 | + +show_help() |
| 132 | + } |
| 133 | + class markdown.sh { |
| 134 | + +manage_section() |
| 135 | + +append_link() |
| 136 | + } |
| 137 | + class llm.sh { |
| 138 | + +generate_response() |
| 139 | + +build_prompt() |
| 140 | + } |
| 141 | + class project.sh { |
| 142 | + +get_project_title() |
| 143 | + +get_version_info() |
| 144 | + } |
| 145 | + class history.sh { |
| 146 | + +build_history() |
| 147 | + +summarize_commit() |
| 148 | + } |
| 149 | + class commands.sh { |
| 150 | + +cmd_changelog() |
| 151 | + +cmd_document() |
| 152 | + +cmd_message() |
| 153 | + } |
| 154 | +
|
| 155 | + giv.sh --> config.sh |
| 156 | + giv.sh --> system.sh |
| 157 | + giv.sh --> args.sh |
| 158 | + giv.sh --> markdown.sh |
| 159 | + giv.sh --> llm.sh |
| 160 | + giv.sh --> project.sh |
| 161 | + giv.sh --> history.sh |
| 162 | + giv.sh --> commands.sh |
| 163 | + commands.sh --> history.sh |
| 164 | + commands.sh --> llm.sh |
| 165 | + commands.sh --> markdown.sh |
| 166 | + history.sh --> project.sh |
| 167 | + llm.sh --> project.sh |
| 168 | + markdown.sh --> system.sh |
| 169 | +``` |
| 170 | + |
| 171 | +This should give you a clear view of how the scripts interconnect, the data each component handles, and the flow of execution through the tool. |
| 172 | + |
| 173 | +[1]: /src/giv.sh "giv.sh" |
| 174 | +[2]: /src/config.sh "config.sh" |
| 175 | +[3]: /src/system.sh "system.sh" |
| 176 | +[4]: /src/args.sh "args.sh" |
| 177 | +[5]: /src/markdown.sh "markdown.sh" |
| 178 | +[6]: /src/llm.sh |
| 179 | +[7]: /src/project.sh |
| 180 | +[8]: /src/history.sh |
| 181 | +[9]: /src/commands.sh |
| 182 | + |
| 183 | +Across the giv-CLI tool, there are five primary **data domains**—each holding specific values—and the `document` subcommand orchestrates several modules in a well-defined call sequence. Below is a data-structure diagram showing the domains and their key contents, then a detailed sequence diagram illustrating exactly how `giv document` runs under the hood. |
| 184 | + |
| 185 | +--- |
| 186 | + |
| 187 | +## Data Domains and Their Contents |
| 188 | + |
| 189 | +```mermaid |
| 190 | +classDiagram |
| 191 | + %% Data Domains |
| 192 | + class GitData { |
| 193 | + +commits: List<Commit SHA> |
| 194 | + +diffs: Unified diff text |
| 195 | + +pathspec: String |
| 196 | + +tags: List<String> |
| 197 | + +revisionRange: String |
| 198 | + } |
| 199 | + class ProjectMetadata { |
| 200 | + +projectTitle: String |
| 201 | + +version: String |
| 202 | + +versionFile: File path |
| 203 | + } |
| 204 | + class PromptTemplates { |
| 205 | + +name: String |
| 206 | + +templateFile: Path |
| 207 | + +tokens: Map<String,String> |
| 208 | + } |
| 209 | + class GeneratedContent { |
| 210 | + +summary: Markdown text |
| 211 | + +changelog: Markdown text |
| 212 | + +releaseNotes: Markdown text |
| 213 | + +announcement: Markdown text |
| 214 | + } |
| 215 | + class ConfigState { |
| 216 | + +GIV_HOME: Path |
| 217 | + +CACHE_DIR: Path |
| 218 | + +TMP_DIR: Path |
| 219 | + +DEBUG: Boolean |
| 220 | + +MODEL: String |
| 221 | + +API_KEY: String |
| 222 | + } |
| 223 | +
|
| 224 | + %% Relationships |
| 225 | + ConfigState --> GitData : configures |
| 226 | + ConfigState --> PromptTemplates : points to |
| 227 | + GitData <--> GeneratedContent : source for |
| 228 | + ProjectMetadata <--> GeneratedContent : metadata in |
| 229 | + PromptTemplates <-- GeneratedContent : drives format |
| 230 | +``` |
| 231 | + |
| 232 | +* **GitData**: all raw Git artifacts (commits, diffs, tags, revision ranges, pathspecs) used to build histories and summaries. |
| 233 | +* **ProjectMetadata**: extracted from files like `package.json` or `pyproject.toml`—contains project title and version info. |
| 234 | +* **PromptTemplates**: stored under `templates/`, each named (e.g. `summary_prompt.md`, `changelog_prompt.md`, `document_prompt.md`) with substitution tokens. |
| 235 | +* **GeneratedContent**: the AI-produced Markdown blobs (commit messages, changelogs, release notes, documents, announcements). |
| 236 | +* **ConfigState**: CLI configuration and state in `.giv/` (home, cache, temp dirs), debug flags, AI model choice, API credentials. |
| 237 | + |
| 238 | +--- |
| 239 | + |
| 240 | +## Sequence of `giv document --prompt-file <file> <range>` |
| 241 | + |
| 242 | +```mermaid |
| 243 | +sequenceDiagram |
| 244 | + participant User |
| 245 | + participant giv.sh |
| 246 | + participant args.sh |
| 247 | + participant system.sh |
| 248 | + participant history.sh |
| 249 | + participant project.sh |
| 250 | + participant llm.sh |
| 251 | + participant markdown.sh |
| 252 | + participant OutputFile as "DOCUMENT.md" |
| 253 | +
|
| 254 | + User->>giv.sh: "giv document --prompt-file templates/document_prompt.md v1.2.0..HEAD" |
| 255 | + alt First time after cloning |
| 256 | + giv.sh->>system.sh: ensure_giv_dir_init() |
| 257 | + system.sh-->>giv.sh: .giv/ dirs created |
| 258 | + end |
| 259 | + giv.sh->>args.sh: parse_args(...) |
| 260 | + args.sh-->>giv.sh: set GIV_PROMPT_FILE, GIV_REV_RANGE, etc. |
| 261 | +
|
| 262 | + giv.sh->>history.sh: summarize_target("v1.2.0..HEAD") |
| 263 | + history.sh->>history.sh: build_history("v1.2.0..HEAD") |
| 264 | + history.sh->>project.sh: get_project_title() |
| 265 | + project.sh-->>history.sh: "My Project" |
| 266 | + history.sh->>project.sh: get_version_info("v1.2.0") |
| 267 | + project.sh-->>history.sh: "1.2.0" |
| 268 | +
|
| 269 | + history.sh->>llm.sh: build_prompt(templates/document_prompt.md,history.md,title, version) |
| 270 | + llm.sh-->>history.sh: fullPrompt |
| 271 | + history.sh->>llm.sh: generate_response(fullPrompt) |
| 272 | + llm.sh-->>history.sh: aiDocumentContent.md |
| 273 | +
|
| 274 | + history.sh-->>giv.sh: /tmp/giv_document_output.md |
| 275 | + giv.sh->>markdown.sh: write_output(/tmp/giv_document_output.md,"DOCUMENT.md") |
| 276 | + markdown.sh-->>giv.sh: DOCUMENT.md written |
| 277 | +
|
| 278 | + giv.sh->>OutputFile: display("DOCUMENT.md") |
| 279 | +``` |
| 280 | + |
| 281 | +1. **Initialization** (once): creates `.giv/` directories. |
| 282 | +2. **Argument Parsing**: `args.sh` sets up global vars (prompt file, revision range). |
| 283 | +3. **History Extraction**: `history.sh` builds a unified history for the given range, invoking `project.sh` for title/version. |
| 284 | +4. **Prompt Assembly**: `llm.sh` merges the template, history, and metadata into a single prompt. |
| 285 | +5. **AI Generation**: same module calls out to remote/local LLM, returns the document text. |
| 286 | +6. **Output**: `markdown.sh` writes the result to `DOCUMENT.md` and the CLI presents it. |
| 287 | + |
| 288 | +These diagrams and explanations should give you a clear map of **what data lives where** and **how the `document` flow unfolds** end-to-end. |
0 commit comments