You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Refactor argument parsing and configuration handling
- Improved the `parse_args` function in `args.sh` to handle configuration file loading more robustly and to ensure that the correct values are set for API model, URL, and key.
- Enhanced the `config.sh` command to normalize keys and improve error handling for missing configuration files.
- Updated `history.sh` to source configuration and project metadata conditionally based on the test environment.
- Modified `llm.sh` to handle API responses more gracefully, including improved error messages and content extraction using `jq` if available.
- Added a utility function in `markdown.sh` to conditionally use `glow` for markdown output.
- Improved project metadata extraction logic in `project_metadata.sh` to ensure project type detection is consistent and robust.
- Enhanced temporary file creation in `system.sh` to ensure proper cleanup and handling of temporary files.
- Updated tests in `summarize_commit.bats`, `summarize_target.bats`, `test_parse_args.bats`, and `test_version_extraction.bats` to ensure proper setup and teardown, including configuration file creation for consistent test behavior.
Copy file name to clipboardExpand all lines: docs/architecture.md
+72-37Lines changed: 72 additions & 37 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,6 +1,13 @@
1
1
# Architecture
2
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.
3
+
A quick overview: giv is a POSIX-compliant shell script suite w### Changelog Generation
4
+
5
+
The `changelog.sh` subcommand follows:
6
+
7
+
1. Summarize commits/ranges with `summarize_target`.
8
+
2. Build the changelog prompt (`changelog_prompt.md`) via `build_prompt`.
9
+
3. Generate content (`generate_from_prompt`).
10
+
4. Update `CHANGELOG.md` using `manage_section` and append a "Managed by giv" link.n entrypoint (`giv.sh`) initializes the 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 (via `changelog.sh`), release-notes and announcements (via `document.sh`), 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
11
5
12
## Repository Structure
6
13
@@ -10,7 +17,7 @@ The main script, **giv.sh**, locates the library, template, and docs directories
10
17
11
18
### Configuration Module
12
19
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]).
20
+
**config.sh**centralizes all configuration logic. It 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.). All configuration keys are normalized via a dedicated `normalize_key()` function to ensure consistent access and override precedence. The module also handles loading from `.giv/config`, environment variables, and CLI arguments, applying a strict order of precedence and robust error handling for missing or malformed config values. This guarantees predictable, portable configuration across all scripts and environments. ([config.sh][2])
14
21
15
22
### System Utilities
16
23
@@ -22,32 +29,56 @@ The main script, **giv.sh**, locates the library, template, and docs directories
22
29
23
30
### Markdown Handling
24
31
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]).
32
+
**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` (with fallback to `cat` if unavailable) ([markdown.sh][5]).
26
33
27
34
### LLM Integration
28
35
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
-
**metadata.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 ([metadata.sh][7]).
36
+
**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`). It includes robust error handling and a fallback to `jq` for JSON parsing ([llm.sh][6]).
34
37
35
38
### Centralized Metadata Retrieval
36
39
37
-
**project_metadata.sh**now includes a centralized function, `get_metadata_value`, which retrieves metadata values (e.g., version, title) based on the project type. This function is used across scripts like `history.sh` and `llm.sh` to ensure consistent and modular metadata management. The project type is detected during initialization and stored in the configuration for runtime use.
40
+
**project_metadata.sh** includes a centralized function, `get_metadata_value`, which retrieves metadata values (e.g., version, title) based on the project type. This function is used across scripts like `history.sh` and `llm.sh` to ensure consistent and modular metadata management. The project type is detected during initialization and stored in the configuration for runtime use.
38
41
39
42
### History Extraction
40
43
41
-
**history.sh** provides utilities for summarizing Git history, extracting TODO changes, and caching summaries ([history.sh][8]).
44
+
**history.sh** provides utilities for summarizing Git history, extracting TODO changes, and caching summaries. It consolidates diff logic in a single `get_diff` function and ensures strict error handling and cleanup of temporary files ([history.sh][8]).
42
45
43
46
### Subcommand Implementations
44
47
45
-
**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]).
48
+
Each subcommand in the `giv` CLI is implemented as a separate `.sh` script located in the `src/commands/` folder. The main `giv.sh` script detects the subcommand and delegates execution to the corresponding script. The architecture has recently evolved to support a more generic and modular approach:
49
+
50
+
1.**Generic Document Driver (`document.sh`)**:
51
+
- Subcommands like `announcement.sh`, `release-notes.sh`, and `summary.sh` now act as thin wrappers that delegate their functionality to `document.sh`.
52
+
- These scripts pass specific templates (e.g., `announcement_prompt.md`, `release_notes_prompt.md`, `final_summary_prompt.md`) to `document.sh` for processing.
53
+
- The `document` subcommand itself allows arbitrary prompt files via `--prompt-file`, supporting custom document types and workflows.
54
+
55
+
2.**Direct Implementations**:
56
+
- Scripts like `changelog.sh` and `message.sh` currently implement their logic directly, but there is an ongoing migration to unify all document-like subcommands under the generic driver for consistency and maintainability.
57
+
- These scripts handle argument parsing, Git history summarization, and AI prompt generation within the script.
58
+
59
+
3.**Shared Functionality**:
60
+
- Common argument parsing and utility functions are provided by `document_args.sh` and other shared scripts. The new `parse_document_args` function is used for all document-related subcommands to ensure consistent flag handling (e.g., `--prompt-file`, `--project-type`).
61
+
62
+
4.**Execution Flow and Error Handling**:
63
+
- The main `giv.sh` script identifies the subcommand and executes the corresponding `.sh` file from the `commands` folder.
64
+
- If the subcommand script is not found, an error message is displayed with a list of available subcommands.
65
+
- All subcommands now include improved error handling: missing dependencies, invalid config, or failed AI calls are surfaced to the user with clear messages and exit codes. Optional dependencies (e.g., Glow, Ollama, GitHub CLI) are checked at runtime, and warnings are issued if unavailable.
66
+
67
+
This modular structure ensures that each subcommand is self-contained and easy to maintain, while shared functionality is centralized for reuse. The ongoing migration aims to further unify subcommand logic and reduce duplication.
68
+
## Testing and Error Handling
69
+
70
+
- The project includes an extensive test suite under `tests/`, covering all major workflows and edge cases. Tests are run in sandboxed environments to ensure reliability and portability.
71
+
- Error handling is robust: missing dependencies, invalid config, or failed AI calls result in clear user-facing messages and non-zero exit codes. Warnings are issued for optional but recommended settings.
72
+
- Users can opt for manual review before saving generated content, providing an additional layer of safety.
73
+
74
+
---
75
+
76
+
These updates ensure the documentation accurately reflects the current and planned architecture, workflows, error handling, and testing strategy of the giv CLI tool.
46
77
47
78
## Data Domains
48
79
49
80
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]).
50
-
2.**Project Metadata**: Version files (`package.json`, etc.), extracted versions (`get_version_info`), and project titles (`get_project_title`) ([metadata.sh][7]).
81
+
2.**Project Metadata**: Version files (`package.json`, etc.), extracted versions (`get_version_info`), and project titles (`get_project_title`) ([project_metadata.sh][7]).
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]).
53
84
5.**Configuration & State**: Stored in `.giv/config`, `.giv/cache`, `.giv/.tmp`, and optionally `.giv/templates` (after `init`) ([system.sh][3]).
@@ -75,16 +106,16 @@ The `summarize_commit` function in **history.sh** orchestrates:
75
106
76
107
### Release-Notes & Announcements
77
108
78
-
Both use the generic `cmd_document` driver:
109
+
Both use the generic `document.sh` subcommand as their driver:
79
110
80
111
1. Summarize history into temp file.
81
112
2. Build prompt from `release_notes_prompt.md` or `announcement_prompt.md`.
82
-
3. Call `generate_from_prompt` with tailored temperature and context window ([giv.sh][1]).
113
+
3. Call `generate_from_prompt` with tailored temperature and context window.
83
114
4. Output to `RELEASE_NOTES.md` or `ANNOUNCEMENT.md`.
84
115
85
116
### Generic Document Generation
86
117
87
-
The `document` subcommand invokes `cmd_document` with a user-supplied `--prompt-file`, enabling arbitrary AI-driven reports over any revision/pathspec ([commands.sh][9]).
118
+
The `document` subcommand invokes `document.sh` with a user-supplied `--prompt-file`, enabling arbitrary AI-driven reports over any revision/pathspec.
88
119
89
120
## Architecture Diagrams
90
121
@@ -110,7 +141,7 @@ sequenceDiagram
110
141
History-->>giv.sh: summaries file
111
142
giv.sh->>Markdown: manage_section(...)
112
143
Markdown-->>giv.sh: updated Markdown
113
-
giv.sh->>Output: write CHANGELOG.md
144
+
giv.sh->>Output: write
114
145
```
115
146
116
147
### Class Diagram
@@ -142,33 +173,37 @@ classDiagram
142
173
+generate_response()
143
174
+build_prompt()
144
175
}
145
-
class metadata.sh {
176
+
class project_metadata.sh {
146
177
+get_project_title()
147
178
+get_version_info()
179
+
+get_metadata_value()
148
180
}
149
181
class history.sh {
150
182
+build_history()
151
183
+summarize_commit()
152
184
}
153
-
class commands.sh {
154
-
+cmd_changelog()
155
-
+cmd_document()
156
-
+cmd_message()
185
+
class "commands/*.sh" {
186
+
+changelog.sh
187
+
+document.sh
188
+
+message.sh
189
+
+announcement.sh
190
+
+release-notes.sh
191
+
+summary.sh
157
192
}
158
193
159
194
giv.sh --> config.sh
160
195
giv.sh --> system.sh
161
196
giv.sh --> args.sh
162
197
giv.sh --> markdown.sh
163
198
giv.sh --> llm.sh
164
-
giv.sh --> metadata.sh
199
+
giv.sh --> project_metadata.sh
165
200
giv.sh --> history.sh
166
-
giv.sh --> commands.sh
167
-
commands.sh --> history.sh
168
-
commands.sh --> llm.sh
169
-
commands.sh --> markdown.sh
170
-
history.sh --> metadata.sh
171
-
llm.sh --> metadata.sh
201
+
giv.sh --> "commands/*.sh"
202
+
"commands/*.sh" --> history.sh
203
+
"commands/*.sh" --> llm.sh
204
+
"commands/*.sh" --> markdown.sh
205
+
history.sh --> project_metadata.sh
206
+
llm.sh --> project_metadata.sh
172
207
markdown.sh --> system.sh
173
208
```
174
209
@@ -180,9 +215,9 @@ This should give you a clear view of how the scripts interconnect, the data each
180
215
[4]: /src/args.sh"args.sh"
181
216
[5]: /src/markdown.sh"markdown.sh"
182
217
[6]: /src/llm.sh
183
-
[7]: /src/metadata.sh
218
+
[7]: /src/project_metadata.sh
184
219
[8]: /src/history.sh
185
-
[9]: /src/commands.sh
220
+
[9]: /src/commands/
186
221
187
222
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.
0 commit comments