conveoconfi 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- conveoconfi-0.1.0/.agents/.gitignore +1 -0
- conveoconfi-0.1.0/.agents/GUIDELINES.md +4 -0
- conveoconfi-0.1.0/.agents/PRD.md +163 -0
- conveoconfi-0.1.0/.agents/PROGRESS.md +100 -0
- conveoconfi-0.1.0/.agents/code-standards/conventional-commits-messages.md +131 -0
- conveoconfi-0.1.0/.agents/issues/001-bootstrap-importable-library-package.md +30 -0
- conveoconfi-0.1.0/.agents/issues/002-create-config-files-from-project-templates.md +24 -0
- conveoconfi-0.1.0/.agents/issues/003-complete-existing-config-files-recursively.md +26 -0
- conveoconfi-0.1.0/.agents/issues/004-preserve-legacy-file-operations.md +24 -0
- conveoconfi-0.1.0/.agents/issues/005-preserve-legacy-parameter-reads.md +31 -0
- conveoconfi-0.1.0/.agents/issues/006-add-source-project-compatibility-fixtures.md +31 -0
- conveoconfi-0.1.0/.agents/issues/007-document-migration-path.md +23 -0
- conveoconfi-0.1.0/.agents/issues/008-review-template-discovery-compatibility-decision.md +36 -0
- conveoconfi-0.1.0/.agents/skills/grill-me/SKILL.md +10 -0
- conveoconfi-0.1.0/.agents/skills/latest-commit/SKILL.md +16 -0
- conveoconfi-0.1.0/.agents/skills/pytest-single-file/SKILL.md +9 -0
- conveoconfi-0.1.0/.agents/skills/ralph/SKILL.md +12 -0
- conveoconfi-0.1.0/.agents/skills/to-issues/SKILL.md +85 -0
- conveoconfi-0.1.0/.agents/skills/to-prd/SKILL.md +80 -0
- conveoconfi-0.1.0/.gitignore +10 -0
- conveoconfi-0.1.0/.opencode/.gitignore +1 -0
- conveoconfi-0.1.0/.opencode/opencode.json +22 -0
- conveoconfi-0.1.0/.python-version +1 -0
- conveoconfi-0.1.0/PKG-INFO +118 -0
- conveoconfi-0.1.0/README.md +108 -0
- conveoconfi-0.1.0/pyproject.toml +21 -0
- conveoconfi-0.1.0/src/conveoconfi/__init__.py +21 -0
- conveoconfi-0.1.0/src/conveoconfi/config_files.py +192 -0
- conveoconfi-0.1.0/tests/test_config_creation.py +301 -0
- conveoconfi-0.1.0/tests/test_import.py +17 -0
- conveoconfi-0.1.0/tests/test_readme.py +46 -0
- conveoconfi-0.1.0/tests/test_source_project_compatibility.py +168 -0
- conveoconfi-0.1.0/uv.lock +139 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
*
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
## Commit Rules
|
|
2
|
+
|
|
3
|
+
- When you make a git commit, always use `Semantic Commit Messages` described in the document @.agents/code-standards/conventional-commits-messages.md
|
|
4
|
+
- When you create or update a "markdown" `.md` file in a "dot folder" `.folder` related to documentation, explanation, task/issue reporting or logging the work, use the skill `latest-commit` to track when exactly the file was created or updated.
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
## Problem Statement
|
|
2
|
+
|
|
3
|
+
The projects `cheapchocolate`, `ohmyscrapper`, and `aphantasist` each carry their own copy of a `core.config_files` module. These copies implement the same convention-over-configuration behavior: YAML files are created from bundled defaults when missing, existing YAML files are completed from defaults when new parameters are introduced, and callers can read nested parameters through a small function-based API.
|
|
4
|
+
|
|
5
|
+
Keeping this behavior duplicated across projects makes maintenance risky. A bug fix or behavior improvement has to be copied by hand into every project, and the copies have already diverged: `cheapchocolate` completes missing nested dictionary values, while `ohmyscrapper` and `aphantasist` only complete missing top-level keys. The developer wants a reusable dependency library named `conveoconfi` that can replace each local `config_files.py` with minimal migration work: add the dependency, change imports, and delete the duplicated module.
|
|
6
|
+
|
|
7
|
+
## Solution
|
|
8
|
+
|
|
9
|
+
Create `conveoconfi` as a Python dependency that provides the same public usage surface as the existing `config_files.py` modules while allowing each consuming project to provide its own YAML default templates.
|
|
10
|
+
|
|
11
|
+
From the consuming developer's perspective, migration should be simple:
|
|
12
|
+
|
|
13
|
+
1. Add `conveoconfi` as a Python dependency.
|
|
14
|
+
2. Replace imports from the project-local `core.config_files` module with imports from `conveoconfi`.
|
|
15
|
+
3. Keep existing calls to `create_and_read_config_file`, `complete_config_file`, `overwrite_config_file`, `append_config_file`, `get_param`, `config_file_exists`, and `config_file_path` working.
|
|
16
|
+
4. Delete the old project-local `config_files.py`.
|
|
17
|
+
5. Keep project-specific default YAML files in the consuming project, or explicitly point `conveoconfi` to their default-template directory.
|
|
18
|
+
|
|
19
|
+
The library should preserve the current convention-over-configuration model:
|
|
20
|
+
|
|
21
|
+
- The configured application directory is created when needed.
|
|
22
|
+
- Missing config files are created from default YAML templates.
|
|
23
|
+
- Existing config files are read from disk.
|
|
24
|
+
- Missing parameters are completed from default templates and persisted back to the current config file.
|
|
25
|
+
- Empty or unreadable-as-empty YAML config files are replaced with default content.
|
|
26
|
+
- Parameter reads use `config.yaml` as the root config file by default, matching the existing behavior.
|
|
27
|
+
|
|
28
|
+
## User Stories
|
|
29
|
+
|
|
30
|
+
1. As a maintainer of multiple Python projects, I want one shared configuration library, so that I do not maintain duplicate `config_files.py` modules.
|
|
31
|
+
2. As a maintainer of `cheapchocolate`, I want to replace `cheapchocolate.core.config_files` with `conveoconfi`, so that future config behavior fixes come from one dependency.
|
|
32
|
+
3. As a maintainer of `ohmyscrapper`, I want to replace `ohmyscrapper.core.config_files` with `conveoconfi`, so that the scraper keeps its existing YAML configuration workflow.
|
|
33
|
+
4. As a maintainer of `aphantasist`, I want to replace `aphantasist.core.config_files` with `conveoconfi`, so that the project no longer carries duplicated config utility code.
|
|
34
|
+
5. As a consuming developer, I want the public functions to keep their current names, so that migration is mostly an import change.
|
|
35
|
+
6. As a consuming developer, I want the current function arguments to remain valid, so that existing callers do not require behavioral rewrites.
|
|
36
|
+
7. As a consuming developer, I want `create_and_read_config_file` to create a missing app config directory, so that first-run setup remains automatic.
|
|
37
|
+
8. As a consuming developer, I want `create_and_read_config_file` to create a missing config file from a YAML template, so that users get working defaults without manual setup.
|
|
38
|
+
9. As a consuming developer, I want `create_and_read_config_file` to return parsed YAML data, so that existing code can continue reading dict-like config values.
|
|
39
|
+
10. As a consuming developer, I want `create_and_read_config_file` to honor `force_default=True`, so that callers can deliberately reset a config file to defaults.
|
|
40
|
+
11. As a consuming developer, I want `create_and_read_config_file` to honor `complete_file=False`, so that callers can read a file without mutating it.
|
|
41
|
+
12. As a consuming developer, I want existing user-provided values to be preserved during completion, so that updates do not overwrite local choices.
|
|
42
|
+
13. As a consuming developer, I want missing top-level keys to be copied from the default template, so that new release defaults appear in old config files.
|
|
43
|
+
14. As a consuming developer, I want missing nested dictionary keys to be copied from the default template, so that newly introduced nested settings work for existing users.
|
|
44
|
+
15. As a maintainer of `cheapchocolate`, I want nested completion to preserve existing nested values, so that existing behavior around `mails.remote_read_state` is retained.
|
|
45
|
+
16. As a maintainer of `ohmyscrapper`, I want nested config sections such as `sniffing`, `queue`, `db`, and `ai` to keep existing user values, so that upgrades do not break scraping behavior.
|
|
46
|
+
17. As a maintainer of `aphantasist`, I want simple config files with only top-level defaults to keep working, so that the library does not require unnecessary project-specific setup.
|
|
47
|
+
18. As a consuming developer, I want empty YAML files to be replaced with defaults, so that an accidental blank config file recovers automatically.
|
|
48
|
+
19. As a consuming developer, I want `overwrite_config_file` to write YAML data to the target config file, so that wrappers can keep their current behavior.
|
|
49
|
+
20. As a consuming developer, I want `append_config_file` to append YAML data and then normalize the file, so that existing append workflows keep working.
|
|
50
|
+
21. As a consuming developer, I want `get_param` to read a child parameter from a parent section in `config.yaml`, so that existing `get_dir`, `get_file`, and similar wrappers keep working.
|
|
51
|
+
22. As a consuming developer, I want `get_param` to raise the same style of exception when a parameter is missing, so that existing error handling remains predictable.
|
|
52
|
+
23. As a consuming developer, I want `config_file_exists` to report whether a config file exists in the app directory, so that seed and setup workflows can branch correctly.
|
|
53
|
+
24. As a consuming developer, I want `config_file_path` to return the filesystem path and ensure the app directory exists, so that wrappers can reuse that convention.
|
|
54
|
+
25. As a consuming developer, I want default templates to be loaded from a project-controlled default-files directory, so that each project can keep its own `config.yaml`, `mail_folders.yaml`, `url_types.yaml`, and `url_sniffing.yaml`.
|
|
55
|
+
26. As a consuming developer, I want to configure the default-template location explicitly, so that templates no longer have to live next to the old duplicated module.
|
|
56
|
+
27. As a consuming developer, I want the library to use safe YAML loading, so that config parsing avoids arbitrary object construction.
|
|
57
|
+
28. As a consuming developer, I want YAML output to stay simple and compatible with existing files, so that generated configs remain easy to inspect and edit.
|
|
58
|
+
29. As a consuming developer, I want Unicode values to be preserved when appending data, so that non-ASCII user-provided config values remain valid.
|
|
59
|
+
30. As a library maintainer, I want the completion algorithm isolated behind a small interface, so that it can be tested without filesystem side effects.
|
|
60
|
+
31. As a library maintainer, I want file IO isolated behind a small interface, so that filesystem behavior can be tested with temporary directories.
|
|
61
|
+
32. As a library maintainer, I want default-template lookup isolated behind a small interface, so that future package-resource support does not disturb callers.
|
|
62
|
+
33. As a library maintainer, I want compatibility tests based on the three source projects, so that regressions are caught before the dependency is adopted.
|
|
63
|
+
34. As a release maintainer, I want package metadata to declare the YAML dependency, so that consumers install everything needed automatically.
|
|
64
|
+
35. As a release maintainer, I want a clear README migration guide, so that project maintainers know exactly which imports to change.
|
|
65
|
+
36. As a release maintainer, I want the first release to be intentionally small, so that adoption risk stays focused on replacing the duplicated module.
|
|
66
|
+
37. As an application user, I want the program to keep starting with sensible defaults, so that I do not need to learn new configuration steps after the migration.
|
|
67
|
+
38. As an application user, I want my existing config files to keep their custom values, so that upgrading a project does not reset my local environment.
|
|
68
|
+
39. As an application user, I want newly released options to appear in my config file automatically, so that I can discover and edit them after an upgrade.
|
|
69
|
+
40. As a consuming developer, I want failures for missing default templates to be explicit, so that packaging mistakes are easy to diagnose.
|
|
70
|
+
|
|
71
|
+
## Implementation Decisions
|
|
72
|
+
|
|
73
|
+
- Build `conveoconfi` as a Python library package rather than an application script.
|
|
74
|
+
- Preserve the function-based API from the existing modules as the initial public compatibility surface.
|
|
75
|
+
- Include these public functions in the compatibility surface: `create_and_read_config_file`, `complete_config_file`, `overwrite_config_file`, `append_config_file`, `get_param`, `config_file_exists`, and `config_file_path`.
|
|
76
|
+
- Keep `file_name`, `default_app_dir`, `force_default=False`, and `complete_file=True` semantics for `create_and_read_config_file`.
|
|
77
|
+
- Keep `get_param(parent_param, param, default_app_dir)` reading from `config.yaml`, matching the existing modules.
|
|
78
|
+
- Keep app-directory creation as part of path resolution, matching the existing `config_file_path` side effect.
|
|
79
|
+
- Add an explicit way to configure where default YAML templates are loaded from, because a reusable dependency cannot assume the templates live in its own package directory.
|
|
80
|
+
- Prefer an explicit default-template directory argument or small configuration object over hidden global state for new code, while keeping the legacy call pattern available for migration.
|
|
81
|
+
- Treat default-template lookup as a deep module: it should hide package-resource and filesystem lookup details behind a stable interface.
|
|
82
|
+
- Treat config completion as a deep module: it should merge missing defaults into existing parsed data without knowing anything about disk paths.
|
|
83
|
+
- Treat YAML file persistence as a deep module: it should centralize safe loading, safe dumping, append-normalize behavior, and recovery from empty YAML files.
|
|
84
|
+
- Use recursive dictionary completion as the target default behavior because it is the stricter convention-over-configuration behavior and is already required by `cheapchocolate`.
|
|
85
|
+
- Preserve existing configured values during recursive completion and only fill missing keys from the template.
|
|
86
|
+
- Do not remove user-defined extra keys that are not present in the template.
|
|
87
|
+
- If a default value is a dictionary but the current value is not a dictionary, preserve the current value rather than replacing it implicitly.
|
|
88
|
+
- If a current value is a dictionary but the default value is not a dictionary, preserve the current value rather than replacing it implicitly.
|
|
89
|
+
- Continue using PyYAML as the YAML implementation because the source projects already depend on `yaml.safe_load`, `yaml.safe_dump`, and `yaml.dump`.
|
|
90
|
+
- Add PyYAML as a package dependency.
|
|
91
|
+
- Keep generated YAML human-readable and compatible with existing source-project behavior.
|
|
92
|
+
- Keep the initial library narrowly focused on YAML template-backed configuration files.
|
|
93
|
+
- Provide documentation showing the migration from `from <project>.core import config_files` to the new dependency import.
|
|
94
|
+
- Provide documentation showing how a consuming project points the library at its own default template directory.
|
|
95
|
+
- Preserve compatibility with Python 3.11 and newer, matching the current project scaffold.
|
|
96
|
+
- Use source-project fixtures based on `cheapchocolate`, `ohmyscrapper`, and `aphantasist` default YAML files to validate compatibility.
|
|
97
|
+
- Capture upstream reference points used for this PRD:
|
|
98
|
+
- `cheapchocolate` main at `4bdd25d522788cb6463c3f0eca494de2a9244a76`, dated `2026-06-17T09:18:39+02:00`, `Bump version: 0.5.4 -> 0.6.0`.
|
|
99
|
+
- `ohmyscrapper` main at `fc6223ddaeade264fcc0e857712ff97d9de49546`, dated `2026-06-07T16:17:25+02:00`, `Bump version: 0.10.1 -> 0.10.2`.
|
|
100
|
+
- `aphantasist` main at `a4f70a890909823dd8d4462529bc20ddc4f375a5`, dated `2026-01-07T18:35:08+01:00`, `Bump version: 0.0.1 -> 0.1.0`.
|
|
101
|
+
|
|
102
|
+
## Testing Decisions
|
|
103
|
+
|
|
104
|
+
- Tests should assert external behavior: returned config data, created files, completed files, preserved user values, raised errors, and filesystem side effects.
|
|
105
|
+
- Tests should not assert private helper call order or internal implementation details.
|
|
106
|
+
- Test the completion module independently with plain dictionaries.
|
|
107
|
+
- Test that top-level missing keys are added from defaults.
|
|
108
|
+
- Test that nested missing keys are added from defaults.
|
|
109
|
+
- Test that existing nested values are preserved.
|
|
110
|
+
- Test that unknown user-defined keys are preserved.
|
|
111
|
+
- Test that scalar-vs-dictionary conflicts preserve existing user values.
|
|
112
|
+
- Test the YAML persistence module with temporary directories and real files.
|
|
113
|
+
- Test creation of a missing config file from a default template.
|
|
114
|
+
- Test recovery when an existing config file parses as `None`.
|
|
115
|
+
- Test `force_default=True` overwrites an existing config file with defaults.
|
|
116
|
+
- Test `complete_file=False` reads without mutating an incomplete file.
|
|
117
|
+
- Test `overwrite_config_file` writes readable YAML.
|
|
118
|
+
- Test `append_config_file` appends data and normalizes duplicate content through a read/write cycle.
|
|
119
|
+
- Test `config_file_exists` before and after file creation.
|
|
120
|
+
- Test `config_file_path` returns the expected path and creates the app directory.
|
|
121
|
+
- Test `get_param` returns a known child value from `config.yaml`.
|
|
122
|
+
- Test `get_param` raises the expected exception message when the child value is missing.
|
|
123
|
+
- Add compatibility fixture tests using the default YAML shapes from `cheapchocolate`, `ohmyscrapper`, and `aphantasist`.
|
|
124
|
+
- Use the `cheapchocolate` existing test `test_complete_config_file_preserves_existing_nested_values` as prior art for nested completion behavior.
|
|
125
|
+
- Use source-project wrapper tests as migration confidence checks, but keep this library's unit tests focused on the shared config-file behavior.
|
|
126
|
+
- Use temporary directories for all filesystem tests so that tests do not touch a developer's real application config.
|
|
127
|
+
|
|
128
|
+
## Out of Scope
|
|
129
|
+
|
|
130
|
+
- Rewriting the consuming projects' higher-level `core.config` wrapper modules.
|
|
131
|
+
- Migrating `cheapchocolate`, `ohmyscrapper`, or `aphantasist` in this PRD.
|
|
132
|
+
- Introducing a new configuration schema language.
|
|
133
|
+
- Validating config values beyond preserving and completing YAML data.
|
|
134
|
+
- Supporting non-YAML config formats.
|
|
135
|
+
- Managing environment-variable overrides.
|
|
136
|
+
- Providing a command-line interface.
|
|
137
|
+
- Providing application-specific default YAML templates inside `conveoconfi`.
|
|
138
|
+
- Removing or renaming legacy public functions during the first compatibility release.
|
|
139
|
+
- Changing project-specific business rules such as mail folders, URL sniffing behavior, queue settings, or scraper policies.
|
|
140
|
+
|
|
141
|
+
## Further Notes
|
|
142
|
+
|
|
143
|
+
The main design risk is default-template discovery. The old modules used `os.path.dirname(os.path.realpath(__file__))` and expected templates in a sibling `default_files` directory. A dependency library cannot infer the consuming project's template directory from its own `__file__`, so the replacement needs a deliberate compatibility mechanism.
|
|
144
|
+
|
|
145
|
+
The second design risk is completion depth. The user request says behavior must be exactly the same regarding usage, but the referenced projects are not behaviorally identical. The PRD chooses recursive completion as the target because it preserves all top-level behavior while also supporting the newer nested-completion behavior already present and tested in `cheapchocolate`.
|
|
146
|
+
|
|
147
|
+
The current `conveoconfi` repository is an initial scaffold with no commits yet, a Python 3.11 project declaration, no dependencies, an empty README, and a simple `main.py` placeholder.
|
|
148
|
+
|
|
149
|
+
## Latest Git Reference
|
|
150
|
+
|
|
151
|
+
Latest commit when this document was written:
|
|
152
|
+
|
|
153
|
+
Hash: none
|
|
154
|
+
Date: none
|
|
155
|
+
Description: this repository has no commits yet
|
|
156
|
+
|
|
157
|
+
## Latest Git Reference for this file
|
|
158
|
+
|
|
159
|
+
Latest commit when this document was written:
|
|
160
|
+
|
|
161
|
+
Hash: none
|
|
162
|
+
Date: none
|
|
163
|
+
Description: this repository has no commits yet
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
## 001 - Bootstrap Importable Library Package
|
|
2
|
+
|
|
3
|
+
Status: complete
|
|
4
|
+
|
|
5
|
+
- Added `src/conveoconfi` as the importable package entrypoint.
|
|
6
|
+
- Exposed the legacy public function names from `conveoconfi.__all__` with clear not-yet-implemented stubs.
|
|
7
|
+
- Declared PyYAML as the runtime YAML dependency and added pytest test metadata.
|
|
8
|
+
- Added an import test covering the package import path and public function names.
|
|
9
|
+
|
|
10
|
+
## 002 - Create Config Files From Project Templates
|
|
11
|
+
|
|
12
|
+
Status: complete
|
|
13
|
+
|
|
14
|
+
- Implemented `config_file_path` so resolving a config path creates the app config directory.
|
|
15
|
+
- Implemented `create_and_read_config_file` for missing file creation from an explicit project template directory, safe YAML loading, human-readable YAML writing, empty-file recovery, and explicit template lookup failures.
|
|
16
|
+
- Added tests covering app directory creation, missing config file creation, empty-file recovery, existing config reads, returned parsed data, and template lookup errors.
|
|
17
|
+
|
|
18
|
+
## 003 - Complete Existing Config Files Recursively
|
|
19
|
+
|
|
20
|
+
Status: complete
|
|
21
|
+
|
|
22
|
+
- Added recursive dictionary completion that fills missing default keys while preserving existing user values and user-defined extra keys.
|
|
23
|
+
- Wired existing-file reads through completion by default, with `complete_file=False` preserving the existing no-mutation read behavior.
|
|
24
|
+
- Implemented `complete_config_file` for direct legacy-style completion calls.
|
|
25
|
+
- Preserved current values when default and current YAML shapes conflict between dictionaries and scalars.
|
|
26
|
+
- Added tests for recursive completion, preservation rules, `force_default=True`, and no-mutation reads.
|
|
27
|
+
|
|
28
|
+
## 004 - Preserve Legacy File Operations
|
|
29
|
+
|
|
30
|
+
Status: complete
|
|
31
|
+
|
|
32
|
+
- Implemented `overwrite_config_file` to write readable YAML to the requested app config file while creating the app directory through path resolution.
|
|
33
|
+
- Implemented `append_config_file` to append YAML data, reload it, and rewrite normalized YAML so duplicate appended keys collapse to a single emitted value.
|
|
34
|
+
- Preserved Unicode values during append normalization through UTF-8 file IO and unicode-enabled YAML dumping.
|
|
35
|
+
- Implemented `config_file_exists` using the shared config path convention.
|
|
36
|
+
- Added temporary-directory filesystem tests for overwrite, append normalization, Unicode preservation, config existence, and config path side effects.
|
|
37
|
+
|
|
38
|
+
## Latest Git Reference for this file
|
|
39
|
+
|
|
40
|
+
Latest commit when this document was written:
|
|
41
|
+
|
|
42
|
+
Hash: 762bb451ae337daefcfe7963df8c794851f86c35
|
|
43
|
+
Date: 2026-06-17T10:23:51+02:00
|
|
44
|
+
Description: feat: create config files from templates
|
|
45
|
+
|
|
46
|
+
## 005 - Preserve Legacy Parameter Reads
|
|
47
|
+
|
|
48
|
+
Status: complete
|
|
49
|
+
|
|
50
|
+
- Implemented `get_param(parent_param, param, default_app_dir, ...)` to read child values from `config.yaml` through the shared create/read/complete path.
|
|
51
|
+
- Kept the legacy three-argument call valid while allowing explicit `default_files_dir` or `default_template_dir` kwargs for template lookup.
|
|
52
|
+
- Added missing-child error handling with a legacy-style exception message that names the requested child and parent.
|
|
53
|
+
- Added tests for successful reads from newly created config files, completion before parameter reads, and missing child parameter errors.
|
|
54
|
+
- Verified with `uv run pytest -q` passing 17 tests.
|
|
55
|
+
|
|
56
|
+
## Latest Git Reference for this file
|
|
57
|
+
|
|
58
|
+
Latest commit when this document was written:
|
|
59
|
+
|
|
60
|
+
Hash: ee84a8cd5952f83fa63a1faa47d919db7a4fa00e
|
|
61
|
+
Date: 2026-06-17T10:37:16+02:00
|
|
62
|
+
Description: feat: preserve legacy parameter reads
|
|
63
|
+
|
|
64
|
+
## 006 - Add Source Project Compatibility Fixtures
|
|
65
|
+
|
|
66
|
+
Status: complete
|
|
67
|
+
|
|
68
|
+
- Added compatibility fixture tests for representative `cheapchocolate`, `ohmyscrapper`, and `aphantasist` YAML config shapes.
|
|
69
|
+
- Verified `cheapchocolate`-style nested mail state completion preserves existing nested values while adding missing nested defaults.
|
|
70
|
+
- Verified `ohmyscrapper`-style sections including `db`, `default_dirs`, `default_files`, `ai`, `sniffing`, and `queue` can be created and recursively completed through the public API.
|
|
71
|
+
- Verified an `aphantasist`-style simple config can be created from defaults and read through `get_param`.
|
|
72
|
+
- Documented the upstream reference commits used for fixture behavior in the test module.
|
|
73
|
+
- Verified with `uv run pytest -q` passing 20 tests.
|
|
74
|
+
|
|
75
|
+
## Latest Git Reference for this file
|
|
76
|
+
|
|
77
|
+
Latest commit when this document was written:
|
|
78
|
+
|
|
79
|
+
Hash: e4e6b33f7dfaa2a528d06a050f5b6c9cb1cd061d
|
|
80
|
+
Date: 2026-06-17T10:41:44+02:00
|
|
81
|
+
Description: test: add source project compatibility fixtures
|
|
82
|
+
|
|
83
|
+
## 007 - Document Migration Path
|
|
84
|
+
|
|
85
|
+
Status: complete
|
|
86
|
+
|
|
87
|
+
- Added README migration documentation covering installation, local dependency declaration, import replacement, default-template directory configuration, supported legacy public functions, and recursive completion behavior.
|
|
88
|
+
- Documented that consuming projects keep their own YAML templates and pass `default_files_dir` or `default_template_dir` explicitly.
|
|
89
|
+
- Called out preservation of existing user values, preservation of extra keys, scalar-versus-dictionary conflict behavior, `force_default=True`, and `complete_file=False`.
|
|
90
|
+
- Added a README regression test that checks the migration guide includes the issue's required topics.
|
|
91
|
+
|
|
92
|
+
## 008 - Review Template Discovery Compatibility Decision
|
|
93
|
+
|
|
94
|
+
Status: complete
|
|
95
|
+
|
|
96
|
+
- Documented the public template-discovery decision in the README.
|
|
97
|
+
- Chose explicit `default_files_dir` or `default_template_dir` configuration for the first stable API.
|
|
98
|
+
- Explained why `conveoconfi` cannot rely on its own package `default_files` directory for consuming project templates.
|
|
99
|
+
- Evaluated caller-package inference as a possible compatibility helper and kept it out of scope because explicit paths are more predictable and already covered by the current API.
|
|
100
|
+
- Added a README regression test for the template-discovery decision.
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
|
|
2
|
+
# Conventional Commits 1.0.0
|
|
3
|
+
|
|
4
|
+
## Summary
|
|
5
|
+
|
|
6
|
+
The Conventional Commits specification is a lightweight convention on top of commit messages.
|
|
7
|
+
It provides an easy set of rules for creating an explicit commit history;
|
|
8
|
+
which makes it easier to write automated tools on top of.
|
|
9
|
+
This convention dovetails with [SemVer](http://semver.org),
|
|
10
|
+
by describing the features, fixes, and breaking changes made in commit messages.
|
|
11
|
+
|
|
12
|
+
The commit message should be structured as follows:
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
<type>[optional scope]: <description>
|
|
18
|
+
|
|
19
|
+
[optional body]
|
|
20
|
+
|
|
21
|
+
[optional footer(s)]
|
|
22
|
+
```
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
<br />
|
|
26
|
+
The commit contains the following structural elements, to communicate intent to the
|
|
27
|
+
consumers of your library:
|
|
28
|
+
|
|
29
|
+
1. **fix:** a commit of the _type_ `fix` patches a bug in your codebase (this correlates with [`PATCH`](http://semver.org/#summary) in Semantic Versioning).
|
|
30
|
+
1. **feat:** a commit of the _type_ `feat` introduces a new feature to the codebase (this correlates with [`MINOR`](http://semver.org/#summary) in Semantic Versioning).
|
|
31
|
+
1. **BREAKING CHANGE:** a commit that has a footer `BREAKING CHANGE:`, or appends a `!` after the type/scope, introduces a breaking API change (correlating with [`MAJOR`](http://semver.org/#summary) in Semantic Versioning).
|
|
32
|
+
A BREAKING CHANGE can be part of commits of any _type_.
|
|
33
|
+
1. _types_ other than `fix:` and `feat:` are allowed, for example [@commitlint/config-conventional](https://github.com/conventional-changelog/commitlint/tree/master/%40commitlint/config-conventional) (based on the [Angular convention](https://github.com/angular/angular/blob/22b96b9/CONTRIBUTING.md#-commit-message-guidelines)) recommends `build:`, `chore:`,
|
|
34
|
+
`ci:`, `docs:`, `style:`, `refactor:`, `perf:`, `test:`, and others.
|
|
35
|
+
1. _footers_ other than `BREAKING CHANGE: <description>` may be provided and follow a convention similar to
|
|
36
|
+
[git trailer format](https://git-scm.com/docs/git-interpret-trailers).
|
|
37
|
+
|
|
38
|
+
Additional types are not mandated by the Conventional Commits specification, and have no implicit effect in Semantic Versioning (unless they include a BREAKING CHANGE).
|
|
39
|
+
<br /><br />
|
|
40
|
+
A scope may be provided to a commit's type, to provide additional contextual information and is contained within parenthesis, e.g., `feat(parser): add ability to parse arrays`.
|
|
41
|
+
|
|
42
|
+
## Examples
|
|
43
|
+
|
|
44
|
+
### Commit message with description and breaking change footer
|
|
45
|
+
```
|
|
46
|
+
feat: allow provided config object to extend other configs
|
|
47
|
+
|
|
48
|
+
BREAKING CHANGE: `extends` key in config file is now used for extending other config files
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Commit message with `!` to draw attention to breaking change
|
|
52
|
+
```
|
|
53
|
+
feat!: send an email to the customer when a product is shipped
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Commit message with scope and `!` to draw attention to breaking change
|
|
57
|
+
```
|
|
58
|
+
feat(api)!: send an email to the customer when a product is shipped
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Commit message with both `!` and BREAKING CHANGE footer
|
|
62
|
+
```
|
|
63
|
+
feat!: drop support for Node 6
|
|
64
|
+
|
|
65
|
+
BREAKING CHANGE: use JavaScript features not available in Node 6.
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Commit message with no body
|
|
69
|
+
```
|
|
70
|
+
docs: correct spelling of CHANGELOG
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Commit message with scope
|
|
74
|
+
```
|
|
75
|
+
feat(lang): add Polish language
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Commit message with multi-paragraph body and multiple footers
|
|
79
|
+
```
|
|
80
|
+
fix: prevent racing of requests
|
|
81
|
+
|
|
82
|
+
Introduce a request id and a reference to latest request. Dismiss
|
|
83
|
+
incoming responses other than from latest request.
|
|
84
|
+
|
|
85
|
+
Remove timeouts which were used to mitigate the racing issue but are
|
|
86
|
+
obsolete now.
|
|
87
|
+
|
|
88
|
+
Reviewed-by: Z
|
|
89
|
+
Refs: #123
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Specification
|
|
93
|
+
|
|
94
|
+
The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in [RFC 2119](https://www.ietf.org/rfc/rfc2119.txt).
|
|
95
|
+
|
|
96
|
+
1. Commits MUST be prefixed with a type, which consists of a noun, `feat`, `fix`, etc., followed
|
|
97
|
+
by the OPTIONAL scope, OPTIONAL `!`, and REQUIRED terminal colon and space.
|
|
98
|
+
1. The type `feat` MUST be used when a commit adds a new feature to your application or library.
|
|
99
|
+
1. The type `fix` MUST be used when a commit represents a bug fix for your application.
|
|
100
|
+
1. A scope MAY be provided after a type. A scope MUST consist of a noun describing a
|
|
101
|
+
section of the codebase surrounded by parenthesis, e.g., `fix(parser):`
|
|
102
|
+
1. A description MUST immediately follow the colon and space after the type/scope prefix.
|
|
103
|
+
The description is a short summary of the code changes, e.g., _fix: array parsing issue when multiple spaces were contained in string_.
|
|
104
|
+
1. A longer commit body MAY be provided after the short description, providing additional contextual information about the code changes. The body MUST begin one blank line after the description.
|
|
105
|
+
1. A commit body is free-form and MAY consist of any number of newline separated paragraphs.
|
|
106
|
+
1. One or more footers MAY be provided one blank line after the body. Each footer MUST consist of
|
|
107
|
+
a word token, followed by either a `:<space>` or `<space>#` separator, followed by a string value (this is inspired by the
|
|
108
|
+
[git trailer convention](https://git-scm.com/docs/git-interpret-trailers)).
|
|
109
|
+
1. A footer's token MUST use `-` in place of whitespace characters, e.g., `Acked-by` (this helps differentiate
|
|
110
|
+
the footer section from a multi-paragraph body). An exception is made for `BREAKING CHANGE`, which MAY also be used as a token.
|
|
111
|
+
1. A footer's value MAY contain spaces and newlines, and parsing MUST terminate when the next valid footer
|
|
112
|
+
token/separator pair is observed.
|
|
113
|
+
1. Breaking changes MUST be indicated in the type/scope prefix of a commit, or as an entry in the
|
|
114
|
+
footer.
|
|
115
|
+
1. If included as a footer, a breaking change MUST consist of the uppercase text BREAKING CHANGE, followed by a colon, space, and description, e.g.,
|
|
116
|
+
_BREAKING CHANGE: environment variables now take precedence over config files_.
|
|
117
|
+
1. If included in the type/scope prefix, breaking changes MUST be indicated by a
|
|
118
|
+
`!` immediately before the `:`. If `!` is used, `BREAKING CHANGE:` MAY be omitted from the footer section,
|
|
119
|
+
and the commit description SHALL be used to describe the breaking change.
|
|
120
|
+
1. Types other than `feat` and `fix` MAY be used in your commit messages, e.g., _docs: update ref docs._
|
|
121
|
+
1. The units of information that make up Conventional Commits MUST NOT be treated as case-sensitive by implementors, with the exception of BREAKING CHANGE which MUST be uppercase.
|
|
122
|
+
1. BREAKING-CHANGE MUST be synonymous with BREAKING CHANGE, when used as a token in a footer.
|
|
123
|
+
|
|
124
|
+
## Why Use Conventional Commits
|
|
125
|
+
|
|
126
|
+
* Automatically generating CHANGELOGs.
|
|
127
|
+
* Automatically determining a semantic version bump (based on the types of commits landed).
|
|
128
|
+
* Communicating the nature of changes to teammates, the public, and other stakeholders.
|
|
129
|
+
* Triggering build and publish processes.
|
|
130
|
+
* Making it easier for people to contribute to your projects, by allowing them to explore
|
|
131
|
+
a more structured commit history.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
## What to build
|
|
2
|
+
|
|
3
|
+
Bootstrap `conveoconfi` as an importable Python library package with PyYAML declared as a dependency and a minimal public API entrypoint ready to expose the legacy config-file functions.
|
|
4
|
+
|
|
5
|
+
## Acceptance criteria
|
|
6
|
+
|
|
7
|
+
- [x] `conveoconfi` can be imported from the project test environment.
|
|
8
|
+
- [x] Package metadata identifies the project as a Python library and declares the YAML dependency needed by the compatibility API.
|
|
9
|
+
- [x] The public package entrypoint is ready to expose the legacy function names without requiring consumers to import from private modules.
|
|
10
|
+
- [x] A basic test verifies the package import path works.
|
|
11
|
+
|
|
12
|
+
## Blocked by
|
|
13
|
+
|
|
14
|
+
None - can start immediately
|
|
15
|
+
|
|
16
|
+
## Type
|
|
17
|
+
|
|
18
|
+
AFK
|
|
19
|
+
|
|
20
|
+
## User stories covered
|
|
21
|
+
|
|
22
|
+
1, 5, 6, 34, 36
|
|
23
|
+
|
|
24
|
+
## Latest Git Reference for this file
|
|
25
|
+
|
|
26
|
+
Latest commit when this document was written:
|
|
27
|
+
|
|
28
|
+
Hash: f00456aa2bca301d4d07852bb6e580fb0b311135
|
|
29
|
+
Date: 2026-06-17T10:19:33+02:00
|
|
30
|
+
Description: feat: bootstrap importable library package
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
## What to build
|
|
2
|
+
|
|
3
|
+
Implement the first end-to-end convention-over-configuration path: a consuming project can point `conveoconfi` at its own default YAML templates, request a config file, and receive parsed config data while the missing or empty app config file is created from the matching template.
|
|
4
|
+
|
|
5
|
+
## Acceptance criteria
|
|
6
|
+
|
|
7
|
+
- [x] A missing app config directory is created automatically when a config file path is resolved.
|
|
8
|
+
- [x] A missing config file is created from the matching project-provided default YAML template.
|
|
9
|
+
- [x] An existing empty YAML config file is replaced with default template content and returned as parsed data.
|
|
10
|
+
- [x] Template lookup failures produce explicit, diagnosable errors.
|
|
11
|
+
- [x] YAML is loaded with safe parsing and written in a human-readable format.
|
|
12
|
+
- [x] Tests cover missing file creation, empty file recovery, returned parsed data, and explicit template-directory use.
|
|
13
|
+
|
|
14
|
+
## Blocked by
|
|
15
|
+
|
|
16
|
+
- 001-bootstrap-importable-library-package.md
|
|
17
|
+
|
|
18
|
+
## Type
|
|
19
|
+
|
|
20
|
+
AFK
|
|
21
|
+
|
|
22
|
+
## User stories covered
|
|
23
|
+
|
|
24
|
+
7, 8, 9, 18, 25, 26, 27, 28, 32, 40
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
## What to build
|
|
2
|
+
|
|
3
|
+
Extend the config read path so existing config files are completed from their default templates, including nested dictionary keys, while preserving all user-provided values and extra keys.
|
|
4
|
+
|
|
5
|
+
## Acceptance criteria
|
|
6
|
+
|
|
7
|
+
- [x] Missing top-level keys are copied from the default template into the current config file.
|
|
8
|
+
- [x] Missing nested dictionary keys are copied from the default template into the current config file.
|
|
9
|
+
- [x] Existing user-provided values are preserved during completion.
|
|
10
|
+
- [x] User-defined extra keys not present in the default template are preserved.
|
|
11
|
+
- [x] Scalar-versus-dictionary conflicts preserve the current user value rather than replacing it implicitly.
|
|
12
|
+
- [x] `force_default=True` overwrites an existing config file with defaults.
|
|
13
|
+
- [x] `complete_file=False` reads an incomplete existing config file without mutating it.
|
|
14
|
+
- [x] Tests cover recursive completion, preservation rules, force-default behavior, and no-mutation reads.
|
|
15
|
+
|
|
16
|
+
## Blocked by
|
|
17
|
+
|
|
18
|
+
- 002-create-config-files-from-project-templates.md
|
|
19
|
+
|
|
20
|
+
## Type
|
|
21
|
+
|
|
22
|
+
AFK
|
|
23
|
+
|
|
24
|
+
## User stories covered
|
|
25
|
+
|
|
26
|
+
10, 11, 12, 13, 14, 15, 16, 17, 30, 37, 38, 39
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
## What to build
|
|
2
|
+
|
|
3
|
+
Preserve the legacy filesystem operations used by the source projects: overwriting YAML config files, append-normalizing YAML data, checking config-file existence, and returning config-file paths while keeping app-directory creation behavior.
|
|
4
|
+
|
|
5
|
+
## Acceptance criteria
|
|
6
|
+
|
|
7
|
+
- [x] `overwrite_config_file` writes readable YAML data to the requested app config file.
|
|
8
|
+
- [x] `append_config_file` appends YAML data, reloads the file, and rewrites normalized YAML so repeated appended content is not duplicated.
|
|
9
|
+
- [x] `append_config_file` preserves Unicode values.
|
|
10
|
+
- [x] `config_file_exists` returns false before creation and true after the file exists.
|
|
11
|
+
- [x] `config_file_path` returns the expected file path and ensures the app config directory exists.
|
|
12
|
+
- [x] Tests use temporary directories and real files for all filesystem behavior.
|
|
13
|
+
|
|
14
|
+
## Blocked by
|
|
15
|
+
|
|
16
|
+
- 002-create-config-files-from-project-templates.md
|
|
17
|
+
|
|
18
|
+
## Type
|
|
19
|
+
|
|
20
|
+
AFK
|
|
21
|
+
|
|
22
|
+
## User stories covered
|
|
23
|
+
|
|
24
|
+
19, 20, 23, 24, 29, 31
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
## What to build
|
|
2
|
+
|
|
3
|
+
Implement the legacy parameter read path so consuming wrappers can call `get_param(parent_param, param, default_app_dir)` and read child values from `config.yaml` with the same missing-parameter behavior as the old modules.
|
|
4
|
+
|
|
5
|
+
## Acceptance criteria
|
|
6
|
+
|
|
7
|
+
- [x] `get_param` reads `config.yaml` through the same create/read/complete behavior as other config files.
|
|
8
|
+
- [x] `get_param` returns the requested child value from the requested parent section.
|
|
9
|
+
- [x] Missing child parameters raise an exception with the legacy message shape.
|
|
10
|
+
- [x] Tests cover successful reads and missing child parameter errors.
|
|
11
|
+
|
|
12
|
+
## Blocked by
|
|
13
|
+
|
|
14
|
+
- 003-complete-existing-config-files-recursively.md
|
|
15
|
+
- 004-preserve-legacy-file-operations.md
|
|
16
|
+
|
|
17
|
+
## Type
|
|
18
|
+
|
|
19
|
+
AFK
|
|
20
|
+
|
|
21
|
+
## User stories covered
|
|
22
|
+
|
|
23
|
+
21, 22
|
|
24
|
+
|
|
25
|
+
## Latest Git Reference for this file
|
|
26
|
+
|
|
27
|
+
Latest commit when this document was written:
|
|
28
|
+
|
|
29
|
+
Hash: ee84a8cd5952f83fa63a1faa47d919db7a4fa00e
|
|
30
|
+
Date: 2026-06-17T10:37:16+02:00
|
|
31
|
+
Description: feat: preserve legacy parameter reads
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
## What to build
|
|
2
|
+
|
|
3
|
+
Add compatibility tests using representative default YAML shapes from `cheapchocolate`, `ohmyscrapper`, and `aphantasist` to prove the reusable library can replace each project's duplicated `config_files.py` behavior.
|
|
4
|
+
|
|
5
|
+
## Acceptance criteria
|
|
6
|
+
|
|
7
|
+
- [x] A `cheapchocolate`-style config fixture verifies nested completion preserves existing nested values and adds missing nested defaults.
|
|
8
|
+
- [x] An `ohmyscrapper`-style config fixture verifies project-specific sections such as `db`, `default_dirs`, `default_files`, `ai`, `sniffing`, and `queue` can be created and completed.
|
|
9
|
+
- [x] An `aphantasist`-style config fixture verifies simple default config files continue to work.
|
|
10
|
+
- [x] Fixture tests exercise the public compatibility API rather than private helpers.
|
|
11
|
+
- [x] Tests document the upstream reference commits used for fixture behavior.
|
|
12
|
+
|
|
13
|
+
## Blocked by
|
|
14
|
+
|
|
15
|
+
- 005-preserve-legacy-parameter-reads.md
|
|
16
|
+
|
|
17
|
+
## Type
|
|
18
|
+
|
|
19
|
+
AFK
|
|
20
|
+
|
|
21
|
+
## User stories covered
|
|
22
|
+
|
|
23
|
+
2, 3, 4, 33
|
|
24
|
+
|
|
25
|
+
## Latest Git Reference for this file
|
|
26
|
+
|
|
27
|
+
Latest commit when this document was written:
|
|
28
|
+
|
|
29
|
+
Hash: e4e6b33f7dfaa2a528d06a050f5b6c9cb1cd061d
|
|
30
|
+
Date: 2026-06-17T10:41:44+02:00
|
|
31
|
+
Description: test: add source project compatibility fixtures
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
## What to build
|
|
2
|
+
|
|
3
|
+
Document how maintainers migrate from duplicated project-local `core.config_files` modules to the shared `conveoconfi` dependency, including installation, import replacement, default-template setup, and removal of the old module.
|
|
4
|
+
|
|
5
|
+
## Acceptance criteria
|
|
6
|
+
|
|
7
|
+
- [x] Documentation shows how to install or declare `conveoconfi` as a dependency.
|
|
8
|
+
- [x] Documentation shows the import replacement from project-local `core.config_files` to the new package.
|
|
9
|
+
- [x] Documentation explains how consuming projects provide or configure their default YAML template directory.
|
|
10
|
+
- [x] Documentation lists the legacy public functions supported by the compatibility API.
|
|
11
|
+
- [x] Documentation calls out recursive completion and preservation of existing user config values.
|
|
12
|
+
|
|
13
|
+
## Blocked by
|
|
14
|
+
|
|
15
|
+
- 005-preserve-legacy-parameter-reads.md
|
|
16
|
+
|
|
17
|
+
## Type
|
|
18
|
+
|
|
19
|
+
AFK
|
|
20
|
+
|
|
21
|
+
## User stories covered
|
|
22
|
+
|
|
23
|
+
2, 3, 4, 25, 26, 35
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
## What to build
|
|
2
|
+
|
|
3
|
+
Review and confirm the final migration ergonomics for default-template discovery before the public API is considered stable: explicit template directory or configuration object only, or an additional compatibility helper that can infer defaults from caller package context.
|
|
4
|
+
|
|
5
|
+
## Acceptance criteria
|
|
6
|
+
|
|
7
|
+
- [x] The chosen template-discovery approach is documented as a public API decision.
|
|
8
|
+
- [x] The decision explains why the library cannot rely on its own package `default_files` directory for consuming project templates.
|
|
9
|
+
- [x] The decision evaluates explicit template-directory configuration against any compatibility helper.
|
|
10
|
+
- [x] Follow-up implementation issues are created or updated if the decision changes the existing issue scope.
|
|
11
|
+
|
|
12
|
+
## Decision
|
|
13
|
+
|
|
14
|
+
Keep the first stable public API explicit: consuming projects pass their
|
|
15
|
+
template directory with `default_files_dir` or `default_template_dir`.
|
|
16
|
+
`conveoconfi` will not infer templates from its own package `default_files`
|
|
17
|
+
directory because the reusable dependency cannot contain each consuming
|
|
18
|
+
application's YAML defaults.
|
|
19
|
+
|
|
20
|
+
A caller-package inference helper was considered, but it would add layout
|
|
21
|
+
assumptions and ambiguity to the migration path. The existing explicit API is
|
|
22
|
+
more predictable, easier to test, and already produces direct lookup errors when
|
|
23
|
+
templates are omitted or missing. No follow-up implementation issue is needed
|
|
24
|
+
because the current issue scope remains unchanged.
|
|
25
|
+
|
|
26
|
+
## Blocked by
|
|
27
|
+
|
|
28
|
+
- 002-create-config-files-from-project-templates.md
|
|
29
|
+
|
|
30
|
+
## Type
|
|
31
|
+
|
|
32
|
+
HITL
|
|
33
|
+
|
|
34
|
+
## User stories covered
|
|
35
|
+
|
|
36
|
+
25, 26, 40
|