mkforge 0.1.0__tar.gz → 0.2.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.
- mkforge-0.2.0/.github/workflows/ci.yml +35 -0
- mkforge-0.2.0/.gitlab-ci.yml +41 -0
- mkforge-0.2.0/AGENTS.md +196 -0
- mkforge-0.2.0/CLAUDE.md +195 -0
- mkforge-0.2.0/Makefile +45 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/PKG-INFO +21 -6
- {mkforge-0.1.0 → mkforge-0.2.0}/README.md +20 -5
- {mkforge-0.1.0 → mkforge-0.2.0}/docs/API_REFERENCE.md +804 -55
- mkforge-0.2.0/docs/USER_GUIDE.md +1270 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/pyproject.toml +8 -13
- {mkforge-0.1.0 → mkforge-0.2.0}/src/mkforge/__init__.py +4 -0
- mkforge-0.2.0/src/mkforge/slugify.py +44 -0
- mkforge-0.2.0/tests/__init__.py +1 -0
- mkforge-0.2.0/tests/conftest.py +1 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/tests/test_markdown_validation.py +10 -2
- mkforge-0.2.0/tests/test_slugify.py +71 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/tests/test_validation.py +6 -2
- {mkforge-0.1.0 → mkforge-0.2.0}/uv.lock +212 -80
- mkforge-0.2.0/work/.gitkeep +0 -0
- mkforge-0.1.0/.github/workflows/ci.yml +0 -26
- mkforge-0.1.0/.gitlab-ci.yml +0 -55
- mkforge-0.1.0/AGENTS.md +0 -120
- mkforge-0.1.0/CLAUDE.md +0 -121
- mkforge-0.1.0/Makefile +0 -57
- mkforge-0.1.0/docs/USER_GUIDE.md +0 -1053
- mkforge-0.1.0/scripts/__init__.py +0 -1
- mkforge-0.1.0/scripts/check.sh +0 -120
- mkforge-0.1.0/scripts/check_docstrings.py +0 -129
- mkforge-0.1.0/scripts/code_metrics.py +0 -397
- mkforge-0.1.0/scripts/publish.sh +0 -31
- mkforge-0.1.0/scripts/security_deps.sh +0 -13
- mkforge-0.1.0/tests/__init__.py +0 -1
- mkforge-0.1.0/work/.gitkeep +0 -1
- {mkforge-0.1.0 → mkforge-0.2.0}/.github/workflows/publish.yml +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/.gitignore +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/.mkforge +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/.python-version +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/LICENSE +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/demo_report.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/demo_validation.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/demo_verif.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/doc/adr-001-markdown-conformance-verifier.md +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/docs/MARKDOWN_RULES.md +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/docs/SDD.md +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/docs/SRS.md +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/docs/adr/ADR-001-asset-management.md +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/docs/adr/ADR-002-markdown-validation-contracts.md +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/docs/pypi-publication.md +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/main.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/src/mkforge/_metadata.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/src/mkforge/assets.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/src/mkforge/content/__init__.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/src/mkforge/content/_base.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/src/mkforge/content/code.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/src/mkforge/content/image.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/src/mkforge/content/lists.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/src/mkforge/content/misc.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/src/mkforge/content/paragraph.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/src/mkforge/content/table.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/src/mkforge/content/text.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/src/mkforge/document.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/src/mkforge/errors.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/src/mkforge/input_checks.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/src/mkforge/py.typed +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/src/mkforge/rendering.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/src/mkforge/validation/__init__.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/src/mkforge/validation/markdown_contracts.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/src/mkforge/verification/__init__.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/src/mkforge/verification/api.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/src/mkforge/verification/diagnostic_pattern.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/src/mkforge/verification/policy.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/src/mkforge/verification/registry.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/src/mkforge/verification/rules/__init__.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/src/mkforge/verification/rules/gfm/__init__.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/src/mkforge/verification/rules/gfm/gfm001_table_delimiter.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/src/mkforge/verification/rules/gfm/gfm002_table_column_count.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/src/mkforge/verification/rules/gfm/gfm003_task_list_marker.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/src/mkforge/verification/rules/markdown/__init__.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/src/mkforge/verification/rules/markdown/_shared.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/src/mkforge/verification/rules/markdown/markdownlint_remaining.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/src/mkforge/verification/rules/markdown/md001_heading_increment.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/src/mkforge/verification/rules/markdown/md002_first_heading_level.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/src/mkforge/verification/rules/markdown/md003_heading_style.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/src/mkforge/verification/rules/markdown/md004_unordered_list_style.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/src/mkforge/verification/rules/markdown/md005_md006_md007_list_indentation.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/src/mkforge/verification/rules/markdown/md009_trailing_spaces.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/src/mkforge/verification/rules/markdown/md010_hard_tabs.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/src/mkforge/verification/rules/markdown/md011_reversed_link_syntax.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/src/mkforge/verification/rules/markdown/md012_multiple_blank_lines.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/src/mkforge/verification/rules/markdown/md013_line_length.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/src/mkforge/verification/rules/markdown/md014_command_prompt.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/src/mkforge/verification/rules/markdown/md018_atx_heading_space.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/src/mkforge/verification/rules/markdown/md019_md021_atx_closed_spaces.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/src/mkforge/verification/rules/markdown/md020_closed_atx_heading_space.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/src/mkforge/verification/rules/markdown/md022_md023_heading_blanks.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/src/mkforge/verification/rules/markdown/md024_md025_duplicate_headings.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/src/mkforge/verification/rules/markdown/md026_heading_punctuation.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/src/mkforge/verification/rules/markdown/md027_md028_blockquote.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/src/mkforge/verification/rules/markdown/md029_md030_list_prefix.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/src/mkforge/verification/rules/markdown/md031_md032_fence_list_blanks.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/src/mkforge/verification/rules/markdown/md033_inline_html.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/src/mkforge/verification/rules/markdown/md034_bare_url.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/src/mkforge/verification/rules/markdown/md035_horizontal_rule.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/src/mkforge/verification/rules/markdown/md036_emphasis_heading.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/src/mkforge/verification/rules/markdown/md037_emphasis_marker_space.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/src/mkforge/verification/rules/markdown/md038_code_span_space.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/src/mkforge/verification/rules/markdown/md039_link_text_space.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/src/mkforge/verification/rules/markdown/md040_md041_md046_md047_blocks.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/src/mkforge/verification/rules/markdown/mkf001_local_resource_exists.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/src/mkforge/verification/settings.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/src/mkforge/verification/source_scan.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/tests/expectations.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/tests/test_assets.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/tests/test_e2e.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/tests/test_e2e_verification.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/tests/test_helpers.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/tests/test_markdown_verification.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/tests/test_metadata.py +0 -0
- {mkforge-0.1.0 → mkforge-0.2.0}/tests/test_report_generation.py +0 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Generated by yggtools — do not remove this line.
|
|
2
|
+
name: CI
|
|
3
|
+
|
|
4
|
+
on:
|
|
5
|
+
push:
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
concurrency:
|
|
9
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
10
|
+
cancel-in-progress: true
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
quality:
|
|
14
|
+
name: Quality (Python ${{ matrix.python-version }})
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
strategy:
|
|
17
|
+
fail-fast: false
|
|
18
|
+
matrix:
|
|
19
|
+
python-version: ["3.12", "3.13"]
|
|
20
|
+
steps:
|
|
21
|
+
- uses: actions/checkout@v4
|
|
22
|
+
- uses: astral-sh/setup-uv@v5
|
|
23
|
+
with:
|
|
24
|
+
enable-cache: true
|
|
25
|
+
- run: uv python install ${{ matrix.python-version }}
|
|
26
|
+
- run: uv sync --python ${{ matrix.python-version }}
|
|
27
|
+
- name: Quality pipeline
|
|
28
|
+
run: PYTHONPATH=src uv run python -m yggtools.cli pipeline
|
|
29
|
+
- name: Upload quality reports
|
|
30
|
+
if: always()
|
|
31
|
+
uses: actions/upload-artifact@v4
|
|
32
|
+
with:
|
|
33
|
+
name: quality-py${{ matrix.python-version }}
|
|
34
|
+
path: work/reports/
|
|
35
|
+
if-no-files-found: ignore
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Generated by yggtools — do not remove this line.
|
|
2
|
+
variables:
|
|
3
|
+
UV_CACHE_DIR: "$CI_PROJECT_DIR/.uv-cache"
|
|
4
|
+
|
|
5
|
+
cache:
|
|
6
|
+
key: "$CI_COMMIT_REF_SLUG"
|
|
7
|
+
paths:
|
|
8
|
+
- .uv-cache/
|
|
9
|
+
- .venv/
|
|
10
|
+
|
|
11
|
+
stages:
|
|
12
|
+
- quality
|
|
13
|
+
|
|
14
|
+
.base:
|
|
15
|
+
before_script:
|
|
16
|
+
- pip install uv --quiet
|
|
17
|
+
- uv sync
|
|
18
|
+
|
|
19
|
+
"quality:3.12":
|
|
20
|
+
extends: .base
|
|
21
|
+
stage: quality
|
|
22
|
+
image: python:3.12-slim
|
|
23
|
+
script:
|
|
24
|
+
- PYTHONPATH=src uv run python -m yggtools.cli pipeline
|
|
25
|
+
artifacts:
|
|
26
|
+
when: always
|
|
27
|
+
paths:
|
|
28
|
+
- work/reports/
|
|
29
|
+
expire_in: 7 days
|
|
30
|
+
|
|
31
|
+
"quality:3.13":
|
|
32
|
+
extends: .base
|
|
33
|
+
stage: quality
|
|
34
|
+
image: python:3.13-slim
|
|
35
|
+
script:
|
|
36
|
+
- PYTHONPATH=src uv run python -m yggtools.cli pipeline
|
|
37
|
+
artifacts:
|
|
38
|
+
when: always
|
|
39
|
+
paths:
|
|
40
|
+
- work/reports/
|
|
41
|
+
expire_in: 7 days
|
mkforge-0.2.0/AGENTS.md
ADDED
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
# AI Agent Instructions
|
|
2
|
+
|
|
3
|
+
These instructions apply to all AI coding agents (ChatGPT, GitHub Copilot,
|
|
4
|
+
and other LLM-based tools) working on this repository.
|
|
5
|
+
|
|
6
|
+
## Coding Standards
|
|
7
|
+
|
|
8
|
+
- Strictly follow Python PEP rules and the Google Python Style Guide for all
|
|
9
|
+
Python code.
|
|
10
|
+
- Keep each function's cyclomatic complexity at or below 10.
|
|
11
|
+
- Keep Python modules below 500 lines unless an ADR explicitly justifies a
|
|
12
|
+
larger module.
|
|
13
|
+
- Do not split a module purely to reduce its line count or cyclomatic
|
|
14
|
+
complexity. A split is justified only when the resulting modules have
|
|
15
|
+
genuinely independent reasons to change.
|
|
16
|
+
- Write Google-style docstrings for every function and class, including private
|
|
17
|
+
functions and classes.
|
|
18
|
+
- Write clean, auditable code with simple control flow.
|
|
19
|
+
- Favor clarity over cleverness.
|
|
20
|
+
- Use precise names for modules, classes, functions, variables, and tests.
|
|
21
|
+
- Keep comments rare and useful.
|
|
22
|
+
- Apply SOLID principles strictly:
|
|
23
|
+
- Single Responsibility: each module, class, and function must have one
|
|
24
|
+
clear reason to change.
|
|
25
|
+
- Open/Closed: add behavior through new focused implementations, rules,
|
|
26
|
+
strategies, or registries instead of editing large conditional blocks.
|
|
27
|
+
- Liskov Substitution: implementations of a public protocol must remain
|
|
28
|
+
interchangeable.
|
|
29
|
+
- Interface Segregation: depend on narrow protocols or callables rather
|
|
30
|
+
than broad objects with unrelated responsibilities.
|
|
31
|
+
- Dependency Inversion: high-level workflows depend on stable interfaces,
|
|
32
|
+
not concrete low-level details.
|
|
33
|
+
|
|
34
|
+
## Dependencies
|
|
35
|
+
|
|
36
|
+
- Minimize external dependencies.
|
|
37
|
+
- Prefer Python standard library packages.
|
|
38
|
+
- Do not add third-party dependencies unless there is a clear technical need
|
|
39
|
+
that cannot reasonably be met with the standard library.
|
|
40
|
+
- Explain the reason for any new dependency before adding it.
|
|
41
|
+
|
|
42
|
+
## Implementation Guidance
|
|
43
|
+
|
|
44
|
+
- Start substantial feature work and architecture changes with an Architecture
|
|
45
|
+
Decision Record in `doc/` before implementing code.
|
|
46
|
+
- Keep changes focused on the requested behavior.
|
|
47
|
+
- Keep public interfaces small.
|
|
48
|
+
- Name modules, classes, functions, variables, and tests with business/domain
|
|
49
|
+
vocabulary first.
|
|
50
|
+
- Avoid global mutable state unless there is a clear reason.
|
|
51
|
+
- Prefer deterministic behavior and explicit inputs.
|
|
52
|
+
- Use design patterns deliberately:
|
|
53
|
+
- Strategy when behavior varies by profile, format, rule, or policy.
|
|
54
|
+
- Registry when behavior must be extended without modifying the engine.
|
|
55
|
+
- Adapter when exposing a simple callable or external API.
|
|
56
|
+
- Factory functions when object creation has validation or multiple variants.
|
|
57
|
+
- Write tests for new behavior.
|
|
58
|
+
- Maintain 100% test coverage.
|
|
59
|
+
- Test function docstrings must state the requirement being verified using the
|
|
60
|
+
prefix `Requirement:`.
|
|
61
|
+
- Every module, function, class, method, and test must include a strict
|
|
62
|
+
Google-style docstring, including private functions and classes.
|
|
63
|
+
- Function and method docstrings must include:
|
|
64
|
+
- a precise summary that explains the domain behavior;
|
|
65
|
+
- `Args:` for every parameter except `self` and `cls`;
|
|
66
|
+
- `Returns:` for every non-`None` return value;
|
|
67
|
+
- `Raises:` for every intentionally raised exception.
|
|
68
|
+
- Class docstrings must include `Attributes:` when instances expose public
|
|
69
|
+
attributes.
|
|
70
|
+
|
|
71
|
+
## Project Structure
|
|
72
|
+
|
|
73
|
+
- Source code lives in `src/mkforge/`.
|
|
74
|
+
- Tests live in `tests/`.
|
|
75
|
+
- Temporary outputs (coverage, caches, build artifacts) go into `work/`.
|
|
76
|
+
|
|
77
|
+
## Quality Checks
|
|
78
|
+
|
|
79
|
+
Before finishing code changes, run:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
make check
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Use `make ci` for non-mutating verification.
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## Mode Architecte
|
|
90
|
+
|
|
91
|
+
Activate this mode by saying: "mode architecte".
|
|
92
|
+
|
|
93
|
+
### Posture
|
|
94
|
+
|
|
95
|
+
- **Challenge first.** Before accepting any feature request, ask: Is this
|
|
96
|
+
feature necessary? What problem does it solve? Can an existing mechanism
|
|
97
|
+
handle it? If the request is vague, ask one targeted clarifying question
|
|
98
|
+
before doing anything else.
|
|
99
|
+
- **Incremental ADRs.** Propose one focused ADR per decision. Never bundle
|
|
100
|
+
unrelated decisions in one document.
|
|
101
|
+
- **Simplicity over cleverness.** Prefer fewer abstractions. A flat list of
|
|
102
|
+
steps beats a plugin framework when there are three plugins.
|
|
103
|
+
- **Injection over inheritance.** Pass dependencies explicitly. Never use
|
|
104
|
+
base-class coupling or hidden global state.
|
|
105
|
+
- **Design patterns deliberately.** Use Strategy when behavior varies by
|
|
106
|
+
policy. Use Registry when behavior must be extended without editing the
|
|
107
|
+
engine. Use Adapter to isolate I/O. Use Pipeline for ordered, independently
|
|
108
|
+
testable steps. Do not introduce a pattern for decoration.
|
|
109
|
+
|
|
110
|
+
### Deliverables
|
|
111
|
+
|
|
112
|
+
When asked to design a feature, produce documents in this order:
|
|
113
|
+
|
|
114
|
+
1. **SRS fragment** — list only the requirements that are new or changed. Use
|
|
115
|
+
`REQ-<CATEGORY>-<NN>` identifiers. Each requirement gets one sentence with
|
|
116
|
+
SHALL / SHOULD / MAY. Include acceptance criteria.
|
|
117
|
+
2. **ADR** — one decision, one document. Sections: Context, Decision,
|
|
118
|
+
Consequences, Alternatives rejected. Store in `doc/ADR-NNN-slug.md`.
|
|
119
|
+
3. **SDD section** — update the relevant section of `doc/SDD.md` to reflect
|
|
120
|
+
the design. Include: affected modules, public interfaces changed, data
|
|
121
|
+
flow, error handling, test strategy.
|
|
122
|
+
|
|
123
|
+
### Constraints
|
|
124
|
+
|
|
125
|
+
- SOLID principles strictly applied.
|
|
126
|
+
- Each module, class, and function has one clear reason to change.
|
|
127
|
+
- High-level workflows depend on stable interfaces, not concrete low-level
|
|
128
|
+
details.
|
|
129
|
+
- No module exceeds 500 lines unless an ADR explicitly justifies it.
|
|
130
|
+
- No function has cyclomatic complexity above 10.
|
|
131
|
+
- Public interfaces are small and named with business/domain vocabulary.
|
|
132
|
+
- No global mutable state.
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## Mode Codeur
|
|
137
|
+
|
|
138
|
+
Activate this mode by saying: "mode codeur".
|
|
139
|
+
|
|
140
|
+
### Posture
|
|
141
|
+
|
|
142
|
+
- **Clarity over cleverness.** Write code a junior can read without
|
|
143
|
+
explanation.
|
|
144
|
+
- **PEP-compliant always.** Follow PEP 8, PEP 257 (Google style), PEP 484,
|
|
145
|
+
PEP 526. Run `make check` before declaring done.
|
|
146
|
+
- **100% check coverage.** Every code change must leave `make check` passing.
|
|
147
|
+
Fix ruff, flake8, mypy, bandit, and pytest failures before closing the task.
|
|
148
|
+
- **Defensive programming at boundaries only.** Validate at entry points (CLI
|
|
149
|
+
args, external API responses, file I/O). Trust internal code and framework
|
|
150
|
+
guarantees. Do not add redundant guards inside a function that already
|
|
151
|
+
received a validated value.
|
|
152
|
+
- **Exceptions with intent.** Raise only when the caller genuinely cannot
|
|
153
|
+
continue. Name exceptions with domain vocabulary. Never use bare `except:`.
|
|
154
|
+
Never swallow exceptions silently.
|
|
155
|
+
- **Prefer stdlib, then well-known packages.** Use `pathlib`, `dataclasses`,
|
|
156
|
+
`typing`, `importlib.resources`. Do not add a dependency that the stdlib can
|
|
157
|
+
handle.
|
|
158
|
+
- **Injection over inheritance.** Pass dependencies as arguments. Avoid global
|
|
159
|
+
state.
|
|
160
|
+
|
|
161
|
+
### Coding Standards (Codeur)
|
|
162
|
+
|
|
163
|
+
- Google-style docstrings on every function, method, class — including private
|
|
164
|
+
ones.
|
|
165
|
+
- Function docstrings: summary + `Args:` + `Returns:` + `Raises:`.
|
|
166
|
+
- Class docstrings: summary + `Attributes:` when public attributes exist.
|
|
167
|
+
- Test docstrings use `Requirement:` prefix to state what is being verified.
|
|
168
|
+
- Names use business/domain vocabulary.
|
|
169
|
+
- Cyclomatic complexity <= 10 per function.
|
|
170
|
+
- Module size <= 500 lines (justified by ADR if exceeded).
|
|
171
|
+
|
|
172
|
+
### Testing Strategy
|
|
173
|
+
|
|
174
|
+
For every code change, write:
|
|
175
|
+
|
|
176
|
+
1. **Unit tests** — mock all I/O and subprocess calls. Test one function in
|
|
177
|
+
isolation. Cover the pass path, the fail path, and each `Raises:` clause.
|
|
178
|
+
2. **Integration / end-to-end tests** — at least one test that exercises the
|
|
179
|
+
full workflow without mocking internal modules (only external calls like
|
|
180
|
+
`subprocess`).
|
|
181
|
+
|
|
182
|
+
Test naming: `test_<what>_<condition>`.
|
|
183
|
+
|
|
184
|
+
### Quality Gate
|
|
185
|
+
|
|
186
|
+
Before reporting done, run:
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
make check
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
When fixing linter/type errors:
|
|
193
|
+
- `ruff` errors — fix the code, not `# noqa`.
|
|
194
|
+
- `mypy` errors — add proper type annotations; never use `# type: ignore`.
|
|
195
|
+
- `bandit` B404/B603/B607 on subprocess — use `# nosec BXXX` on the offending
|
|
196
|
+
line.
|
mkforge-0.2.0/CLAUDE.md
ADDED
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
# Claude Code Instructions
|
|
2
|
+
|
|
3
|
+
These instructions apply to the whole repository.
|
|
4
|
+
|
|
5
|
+
## Coding Standards
|
|
6
|
+
|
|
7
|
+
- Strictly follow Python PEP rules and the Google Python Style Guide for all
|
|
8
|
+
Python code.
|
|
9
|
+
- Keep each function's cyclomatic complexity at or below 10.
|
|
10
|
+
- Keep Python modules below 500 lines unless an ADR explicitly justifies a
|
|
11
|
+
larger module.
|
|
12
|
+
- Do not split a module purely to reduce its line count or cyclomatic
|
|
13
|
+
complexity. A split is justified only when the resulting modules have
|
|
14
|
+
genuinely independent reasons to change.
|
|
15
|
+
- Write Google-style docstrings for every function and class, including private
|
|
16
|
+
functions and classes.
|
|
17
|
+
- Write clean, auditable code with simple control flow.
|
|
18
|
+
- Favor clarity over cleverness.
|
|
19
|
+
- Use precise names for modules, classes, functions, variables, and tests.
|
|
20
|
+
- Keep comments rare and useful.
|
|
21
|
+
- Apply SOLID principles strictly:
|
|
22
|
+
- Single Responsibility: each module, class, and function must have one
|
|
23
|
+
clear reason to change.
|
|
24
|
+
- Open/Closed: add behavior through new focused implementations, rules,
|
|
25
|
+
strategies, or registries instead of editing large conditional blocks.
|
|
26
|
+
- Liskov Substitution: implementations of a public protocol must remain
|
|
27
|
+
interchangeable.
|
|
28
|
+
- Interface Segregation: depend on narrow protocols or callables rather
|
|
29
|
+
than broad objects with unrelated responsibilities.
|
|
30
|
+
- Dependency Inversion: high-level workflows depend on stable interfaces,
|
|
31
|
+
not concrete low-level details.
|
|
32
|
+
|
|
33
|
+
## Dependencies
|
|
34
|
+
|
|
35
|
+
- Minimize external dependencies.
|
|
36
|
+
- Prefer Python standard library packages.
|
|
37
|
+
- Do not add third-party dependencies unless there is a clear technical need
|
|
38
|
+
that cannot reasonably be met with the standard library.
|
|
39
|
+
- Explain the reason for any new dependency before adding it.
|
|
40
|
+
|
|
41
|
+
## Implementation Guidance
|
|
42
|
+
|
|
43
|
+
- Start substantial feature work and architecture changes with an Architecture
|
|
44
|
+
Decision Record in `doc/` before implementing code.
|
|
45
|
+
- Keep changes focused on the requested behavior.
|
|
46
|
+
- Keep public interfaces small.
|
|
47
|
+
- Name modules, classes, functions, variables, and tests with business/domain
|
|
48
|
+
vocabulary first.
|
|
49
|
+
- Avoid global mutable state unless there is a clear reason.
|
|
50
|
+
- Prefer deterministic behavior and explicit inputs.
|
|
51
|
+
- Use design patterns deliberately:
|
|
52
|
+
- Strategy when behavior varies by profile, format, rule, or policy.
|
|
53
|
+
- Registry when behavior must be extended without modifying the engine.
|
|
54
|
+
- Adapter when exposing a simple callable or external API.
|
|
55
|
+
- Factory functions when object creation has validation or multiple variants.
|
|
56
|
+
- Write tests for new behavior.
|
|
57
|
+
- Maintain 100% test coverage.
|
|
58
|
+
- Test function docstrings must state the requirement being verified using the
|
|
59
|
+
prefix `Requirement:`.
|
|
60
|
+
- Every module, function, class, method, and test must include a strict
|
|
61
|
+
Google-style docstring, including private functions and classes.
|
|
62
|
+
- Function and method docstrings must include:
|
|
63
|
+
- a precise summary that explains the domain behavior;
|
|
64
|
+
- `Args:` for every parameter except `self` and `cls`;
|
|
65
|
+
- `Returns:` for every non-`None` return value;
|
|
66
|
+
- `Raises:` for every intentionally raised exception.
|
|
67
|
+
- Class docstrings must include `Attributes:` when instances expose public
|
|
68
|
+
attributes.
|
|
69
|
+
|
|
70
|
+
## Project Structure
|
|
71
|
+
|
|
72
|
+
- Source code lives in `src/mkforge/`.
|
|
73
|
+
- Tests live in `tests/`.
|
|
74
|
+
- Temporary outputs (coverage, caches, build artifacts) go into `work/`.
|
|
75
|
+
|
|
76
|
+
## Quality Checks
|
|
77
|
+
|
|
78
|
+
Before finishing code changes, run:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
make check
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Use `make ci` for non-mutating verification.
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## Mode Architecte
|
|
89
|
+
|
|
90
|
+
Activate this mode by saying: "mode architecte".
|
|
91
|
+
|
|
92
|
+
### Posture
|
|
93
|
+
|
|
94
|
+
- **Challenge first.** Before accepting any feature request, ask: Is this
|
|
95
|
+
feature necessary? What problem does it solve? Can an existing mechanism
|
|
96
|
+
handle it? If the request is vague, ask one targeted clarifying question
|
|
97
|
+
before doing anything else.
|
|
98
|
+
- **Incremental ADRs.** Propose one focused ADR per decision. Never bundle
|
|
99
|
+
unrelated decisions in one document.
|
|
100
|
+
- **Simplicity over cleverness.** Prefer fewer abstractions. A flat list of
|
|
101
|
+
steps beats a plugin framework when there are three plugins.
|
|
102
|
+
- **Injection over inheritance.** Pass dependencies explicitly. Never use
|
|
103
|
+
base-class coupling or hidden global state.
|
|
104
|
+
- **Design patterns deliberately.** Use Strategy when behavior varies by
|
|
105
|
+
policy. Use Registry when behavior must be extended without editing the
|
|
106
|
+
engine. Use Adapter to isolate I/O. Use Pipeline for ordered, independently
|
|
107
|
+
testable steps. Do not introduce a pattern for decoration.
|
|
108
|
+
|
|
109
|
+
### Deliverables
|
|
110
|
+
|
|
111
|
+
When asked to design a feature, produce documents in this order:
|
|
112
|
+
|
|
113
|
+
1. **SRS fragment** — list only the requirements that are new or changed. Use
|
|
114
|
+
`REQ-<CATEGORY>-<NN>` identifiers. Each requirement gets one sentence with
|
|
115
|
+
SHALL / SHOULD / MAY. Include acceptance criteria.
|
|
116
|
+
2. **ADR** — one decision, one document. Sections: Context, Decision,
|
|
117
|
+
Consequences, Alternatives rejected. Store in `doc/ADR-NNN-slug.md`.
|
|
118
|
+
3. **SDD section** — update the relevant section of `doc/SDD.md` to reflect
|
|
119
|
+
the design. Include: affected modules, public interfaces changed, data
|
|
120
|
+
flow, error handling, test strategy.
|
|
121
|
+
|
|
122
|
+
### Constraints
|
|
123
|
+
|
|
124
|
+
- SOLID principles strictly applied.
|
|
125
|
+
- Each module, class, and function has one clear reason to change.
|
|
126
|
+
- High-level workflows depend on stable interfaces, not concrete low-level
|
|
127
|
+
details.
|
|
128
|
+
- No module exceeds 500 lines unless an ADR explicitly justifies it.
|
|
129
|
+
- No function has cyclomatic complexity above 10.
|
|
130
|
+
- Public interfaces are small and named with business/domain vocabulary.
|
|
131
|
+
- No global mutable state.
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## Mode Codeur
|
|
136
|
+
|
|
137
|
+
Activate this mode by saying: "mode codeur".
|
|
138
|
+
|
|
139
|
+
### Posture
|
|
140
|
+
|
|
141
|
+
- **Clarity over cleverness.** Write code a junior can read without
|
|
142
|
+
explanation.
|
|
143
|
+
- **PEP-compliant always.** Follow PEP 8, PEP 257 (Google style), PEP 484,
|
|
144
|
+
PEP 526. Run `make check` before declaring done.
|
|
145
|
+
- **100% check coverage.** Every code change must leave `make check` passing.
|
|
146
|
+
Fix ruff, flake8, mypy, bandit, and pytest failures before closing the task.
|
|
147
|
+
- **Defensive programming at boundaries only.** Validate at entry points (CLI
|
|
148
|
+
args, external API responses, file I/O). Trust internal code and framework
|
|
149
|
+
guarantees. Do not add redundant guards inside a function that already
|
|
150
|
+
received a validated value.
|
|
151
|
+
- **Exceptions with intent.** Raise only when the caller genuinely cannot
|
|
152
|
+
continue. Name exceptions with domain vocabulary. Never use bare `except:`.
|
|
153
|
+
Never swallow exceptions silently.
|
|
154
|
+
- **Prefer stdlib, then well-known packages.** Use `pathlib`, `dataclasses`,
|
|
155
|
+
`typing`, `importlib.resources`. Do not add a dependency that the stdlib can
|
|
156
|
+
handle.
|
|
157
|
+
- **Injection over inheritance.** Pass dependencies as arguments. Avoid global
|
|
158
|
+
state.
|
|
159
|
+
|
|
160
|
+
### Coding Standards (Codeur)
|
|
161
|
+
|
|
162
|
+
- Google-style docstrings on every function, method, class — including private
|
|
163
|
+
ones.
|
|
164
|
+
- Function docstrings: summary + `Args:` + `Returns:` + `Raises:`.
|
|
165
|
+
- Class docstrings: summary + `Attributes:` when public attributes exist.
|
|
166
|
+
- Test docstrings use `Requirement:` prefix to state what is being verified.
|
|
167
|
+
- Names use business/domain vocabulary.
|
|
168
|
+
- Cyclomatic complexity <= 10 per function.
|
|
169
|
+
- Module size <= 500 lines (justified by ADR if exceeded).
|
|
170
|
+
|
|
171
|
+
### Testing Strategy
|
|
172
|
+
|
|
173
|
+
For every code change, write:
|
|
174
|
+
|
|
175
|
+
1. **Unit tests** — mock all I/O and subprocess calls. Test one function in
|
|
176
|
+
isolation. Cover the pass path, the fail path, and each `Raises:` clause.
|
|
177
|
+
2. **Integration / end-to-end tests** — at least one test that exercises the
|
|
178
|
+
full workflow without mocking internal modules (only external calls like
|
|
179
|
+
`subprocess`).
|
|
180
|
+
|
|
181
|
+
Test naming: `test_<what>_<condition>`.
|
|
182
|
+
|
|
183
|
+
### Quality Gate
|
|
184
|
+
|
|
185
|
+
Before reporting done, run:
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
make check
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
When fixing linter/type errors:
|
|
192
|
+
- `ruff` errors — fix the code, not `# noqa`.
|
|
193
|
+
- `mypy` errors — add proper type annotations; never use `# type: ignore`.
|
|
194
|
+
- `bandit` B404/B603/B607 on subprocess — use `# nosec BXXX` on the offending
|
|
195
|
+
line.
|
mkforge-0.2.0/Makefile
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Generated by yggtools — do not remove this line.
|
|
2
|
+
|
|
3
|
+
.PHONY: check ci test format lint typecheck metrics security build check-dist publish-test publish clean
|
|
4
|
+
|
|
5
|
+
clean:
|
|
6
|
+
mkdir -p work
|
|
7
|
+
find work -mindepth 1 ! -name .gitkeep -exec rm -rf {} +
|
|
8
|
+
|
|
9
|
+
format:
|
|
10
|
+
uv run ruff format src tests
|
|
11
|
+
|
|
12
|
+
check: clean
|
|
13
|
+
PYTHONPATH=src uv run python -m yggtools.cli pipeline
|
|
14
|
+
|
|
15
|
+
ci: check
|
|
16
|
+
|
|
17
|
+
test: clean
|
|
18
|
+
uv run pytest
|
|
19
|
+
|
|
20
|
+
lint: clean
|
|
21
|
+
uv run ruff check src tests
|
|
22
|
+
|
|
23
|
+
typecheck: clean
|
|
24
|
+
uv run mypy src tests
|
|
25
|
+
|
|
26
|
+
metrics: clean
|
|
27
|
+
PYTHONPATH=src uv run python -m yggtools.cli run metrics
|
|
28
|
+
|
|
29
|
+
security: clean
|
|
30
|
+
PYTHONPATH=src uv run python -m yggtools.cli run security-code
|
|
31
|
+
PYTHONPATH=src uv run python -m yggtools.cli run security-deps
|
|
32
|
+
|
|
33
|
+
build: clean
|
|
34
|
+
rm -rf dist
|
|
35
|
+
uv build --out-dir dist/
|
|
36
|
+
|
|
37
|
+
check-dist: clean
|
|
38
|
+
uv build --out-dir work/dist
|
|
39
|
+
uv run twine check work/dist/*
|
|
40
|
+
|
|
41
|
+
publish-test: check-dist
|
|
42
|
+
uv run twine upload --repository testpypi work/dist/*
|
|
43
|
+
|
|
44
|
+
publish: check-dist
|
|
45
|
+
uv run twine upload work/dist/*
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mkforge
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: Programmatic Markdown report generation for Python.
|
|
5
5
|
Project-URL: Homepage, https://github.com/antoinebarre/mkforge
|
|
6
6
|
Project-URL: Repository, https://github.com/antoinebarre/mkforge
|
|
@@ -73,9 +73,9 @@ For package validation before publishing:
|
|
|
73
73
|
make check-dist
|
|
74
74
|
```
|
|
75
75
|
|
|
76
|
-
Temporary
|
|
77
|
-
|
|
78
|
-
`work/.gitkeep`.
|
|
76
|
+
Temporary quality reports are written under `work/reports/`. Packaging checks
|
|
77
|
+
build distributions under `work/dist/`. The `work/` directory is kept in the
|
|
78
|
+
repository with `work/.gitkeep`.
|
|
79
79
|
|
|
80
80
|
## Example
|
|
81
81
|
|
|
@@ -146,13 +146,28 @@ uv run python demo_verif.py
|
|
|
146
146
|
uv run python demo_validation.py
|
|
147
147
|
```
|
|
148
148
|
|
|
149
|
+
## Heading Slugification
|
|
150
|
+
|
|
151
|
+
```python
|
|
152
|
+
from mkforge import slugify_heading
|
|
153
|
+
|
|
154
|
+
slugify_heading("Analyse des Risques") # "analyse-des-risques"
|
|
155
|
+
slugify_heading("`code` inline") # "code-inline"
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
`slugify_heading` converts a raw heading title into a GitHub-style anchor
|
|
159
|
+
slug: lowercase, inline Markdown markers removed, non-alphanumeric runs
|
|
160
|
+
collapsed to a single hyphen, leading/trailing hyphens trimmed. Unicode
|
|
161
|
+
letters are preserved (case-folded, not transliterated), which keeps slugs
|
|
162
|
+
consistent with the anchors GitHub generates for the same heading.
|
|
163
|
+
|
|
149
164
|
## Relationship With Scribpy
|
|
150
165
|
|
|
151
166
|
MkForge is intended to be independent from Scribpy.
|
|
152
167
|
|
|
153
168
|
- `mkforge` generates Markdown reports from Python data.
|
|
154
169
|
- `scribpy` assembles and builds Markdown documentation projects.
|
|
155
|
-
- `
|
|
170
|
+
- `yggtools` initializes and runs quality gates for Python packages using `uv`.
|
|
156
171
|
|
|
157
|
-
Scribpy and
|
|
172
|
+
Scribpy and yggtools may depend on MkForge for generated reports, but MkForge
|
|
158
173
|
should not depend on either of them.
|
|
@@ -58,9 +58,9 @@ For package validation before publishing:
|
|
|
58
58
|
make check-dist
|
|
59
59
|
```
|
|
60
60
|
|
|
61
|
-
Temporary
|
|
62
|
-
|
|
63
|
-
`work/.gitkeep`.
|
|
61
|
+
Temporary quality reports are written under `work/reports/`. Packaging checks
|
|
62
|
+
build distributions under `work/dist/`. The `work/` directory is kept in the
|
|
63
|
+
repository with `work/.gitkeep`.
|
|
64
64
|
|
|
65
65
|
## Example
|
|
66
66
|
|
|
@@ -131,13 +131,28 @@ uv run python demo_verif.py
|
|
|
131
131
|
uv run python demo_validation.py
|
|
132
132
|
```
|
|
133
133
|
|
|
134
|
+
## Heading Slugification
|
|
135
|
+
|
|
136
|
+
```python
|
|
137
|
+
from mkforge import slugify_heading
|
|
138
|
+
|
|
139
|
+
slugify_heading("Analyse des Risques") # "analyse-des-risques"
|
|
140
|
+
slugify_heading("`code` inline") # "code-inline"
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
`slugify_heading` converts a raw heading title into a GitHub-style anchor
|
|
144
|
+
slug: lowercase, inline Markdown markers removed, non-alphanumeric runs
|
|
145
|
+
collapsed to a single hyphen, leading/trailing hyphens trimmed. Unicode
|
|
146
|
+
letters are preserved (case-folded, not transliterated), which keeps slugs
|
|
147
|
+
consistent with the anchors GitHub generates for the same heading.
|
|
148
|
+
|
|
134
149
|
## Relationship With Scribpy
|
|
135
150
|
|
|
136
151
|
MkForge is intended to be independent from Scribpy.
|
|
137
152
|
|
|
138
153
|
- `mkforge` generates Markdown reports from Python data.
|
|
139
154
|
- `scribpy` assembles and builds Markdown documentation projects.
|
|
140
|
-
- `
|
|
155
|
+
- `yggtools` initializes and runs quality gates for Python packages using `uv`.
|
|
141
156
|
|
|
142
|
-
Scribpy and
|
|
157
|
+
Scribpy and yggtools may depend on MkForge for generated reports, but MkForge
|
|
143
158
|
should not depend on either of them.
|