mkforge 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.
- mkforge-0.1.0/.github/workflows/ci.yml +26 -0
- mkforge-0.1.0/.github/workflows/publish.yml +82 -0
- mkforge-0.1.0/.gitignore +38 -0
- mkforge-0.1.0/.gitlab-ci.yml +55 -0
- mkforge-0.1.0/.mkforge +67 -0
- mkforge-0.1.0/.python-version +1 -0
- mkforge-0.1.0/AGENTS.md +120 -0
- mkforge-0.1.0/CLAUDE.md +121 -0
- mkforge-0.1.0/LICENSE +22 -0
- mkforge-0.1.0/Makefile +57 -0
- mkforge-0.1.0/PKG-INFO +158 -0
- mkforge-0.1.0/README.md +143 -0
- mkforge-0.1.0/demo_report.py +235 -0
- mkforge-0.1.0/demo_validation.py +291 -0
- mkforge-0.1.0/demo_verif.py +236 -0
- mkforge-0.1.0/doc/adr-001-markdown-conformance-verifier.md +197 -0
- mkforge-0.1.0/docs/API_REFERENCE.md +1724 -0
- mkforge-0.1.0/docs/MARKDOWN_RULES.md +958 -0
- mkforge-0.1.0/docs/SDD.md +902 -0
- mkforge-0.1.0/docs/SRS.md +550 -0
- mkforge-0.1.0/docs/USER_GUIDE.md +1053 -0
- mkforge-0.1.0/docs/adr/ADR-001-asset-management.md +142 -0
- mkforge-0.1.0/docs/adr/ADR-002-markdown-validation-contracts.md +98 -0
- mkforge-0.1.0/docs/pypi-publication.md +70 -0
- mkforge-0.1.0/main.py +6 -0
- mkforge-0.1.0/pyproject.toml +98 -0
- mkforge-0.1.0/scripts/__init__.py +1 -0
- mkforge-0.1.0/scripts/check.sh +120 -0
- mkforge-0.1.0/scripts/check_docstrings.py +129 -0
- mkforge-0.1.0/scripts/code_metrics.py +397 -0
- mkforge-0.1.0/scripts/publish.sh +31 -0
- mkforge-0.1.0/scripts/security_deps.sh +13 -0
- mkforge-0.1.0/src/mkforge/__init__.py +76 -0
- mkforge-0.1.0/src/mkforge/_metadata.py +4 -0
- mkforge-0.1.0/src/mkforge/assets.py +387 -0
- mkforge-0.1.0/src/mkforge/content/__init__.py +62 -0
- mkforge-0.1.0/src/mkforge/content/_base.py +26 -0
- mkforge-0.1.0/src/mkforge/content/code.py +39 -0
- mkforge-0.1.0/src/mkforge/content/image.py +42 -0
- mkforge-0.1.0/src/mkforge/content/lists.py +80 -0
- mkforge-0.1.0/src/mkforge/content/misc.py +47 -0
- mkforge-0.1.0/src/mkforge/content/paragraph.py +70 -0
- mkforge-0.1.0/src/mkforge/content/table.py +161 -0
- mkforge-0.1.0/src/mkforge/content/text.py +118 -0
- mkforge-0.1.0/src/mkforge/document.py +314 -0
- mkforge-0.1.0/src/mkforge/errors.py +88 -0
- mkforge-0.1.0/src/mkforge/input_checks.py +93 -0
- mkforge-0.1.0/src/mkforge/py.typed +1 -0
- mkforge-0.1.0/src/mkforge/rendering.py +513 -0
- mkforge-0.1.0/src/mkforge/validation/__init__.py +21 -0
- mkforge-0.1.0/src/mkforge/validation/markdown_contracts.py +667 -0
- mkforge-0.1.0/src/mkforge/verification/__init__.py +25 -0
- mkforge-0.1.0/src/mkforge/verification/api.py +134 -0
- mkforge-0.1.0/src/mkforge/verification/diagnostic_pattern.py +41 -0
- mkforge-0.1.0/src/mkforge/verification/policy.py +121 -0
- mkforge-0.1.0/src/mkforge/verification/registry.py +76 -0
- mkforge-0.1.0/src/mkforge/verification/rules/__init__.py +1 -0
- mkforge-0.1.0/src/mkforge/verification/rules/gfm/__init__.py +1 -0
- mkforge-0.1.0/src/mkforge/verification/rules/gfm/gfm001_table_delimiter.py +97 -0
- mkforge-0.1.0/src/mkforge/verification/rules/gfm/gfm002_table_column_count.py +132 -0
- mkforge-0.1.0/src/mkforge/verification/rules/gfm/gfm003_task_list_marker.py +52 -0
- mkforge-0.1.0/src/mkforge/verification/rules/markdown/__init__.py +1 -0
- mkforge-0.1.0/src/mkforge/verification/rules/markdown/_shared.py +607 -0
- mkforge-0.1.0/src/mkforge/verification/rules/markdown/markdownlint_remaining.py +139 -0
- mkforge-0.1.0/src/mkforge/verification/rules/markdown/md001_heading_increment.py +36 -0
- mkforge-0.1.0/src/mkforge/verification/rules/markdown/md002_first_heading_level.py +42 -0
- mkforge-0.1.0/src/mkforge/verification/rules/markdown/md003_heading_style.py +40 -0
- mkforge-0.1.0/src/mkforge/verification/rules/markdown/md004_unordered_list_style.py +43 -0
- mkforge-0.1.0/src/mkforge/verification/rules/markdown/md005_md006_md007_list_indentation.py +112 -0
- mkforge-0.1.0/src/mkforge/verification/rules/markdown/md009_trailing_spaces.py +40 -0
- mkforge-0.1.0/src/mkforge/verification/rules/markdown/md010_hard_tabs.py +37 -0
- mkforge-0.1.0/src/mkforge/verification/rules/markdown/md011_reversed_link_syntax.py +36 -0
- mkforge-0.1.0/src/mkforge/verification/rules/markdown/md012_multiple_blank_lines.py +38 -0
- mkforge-0.1.0/src/mkforge/verification/rules/markdown/md013_line_length.py +40 -0
- mkforge-0.1.0/src/mkforge/verification/rules/markdown/md014_command_prompt.py +42 -0
- mkforge-0.1.0/src/mkforge/verification/rules/markdown/md018_atx_heading_space.py +36 -0
- mkforge-0.1.0/src/mkforge/verification/rules/markdown/md019_md021_atx_closed_spaces.py +81 -0
- mkforge-0.1.0/src/mkforge/verification/rules/markdown/md020_closed_atx_heading_space.py +39 -0
- mkforge-0.1.0/src/mkforge/verification/rules/markdown/md022_md023_heading_blanks.py +85 -0
- mkforge-0.1.0/src/mkforge/verification/rules/markdown/md024_md025_duplicate_headings.py +84 -0
- mkforge-0.1.0/src/mkforge/verification/rules/markdown/md026_heading_punctuation.py +36 -0
- mkforge-0.1.0/src/mkforge/verification/rules/markdown/md027_md028_blockquote.py +78 -0
- mkforge-0.1.0/src/mkforge/verification/rules/markdown/md029_md030_list_prefix.py +87 -0
- mkforge-0.1.0/src/mkforge/verification/rules/markdown/md031_md032_fence_list_blanks.py +100 -0
- mkforge-0.1.0/src/mkforge/verification/rules/markdown/md033_inline_html.py +41 -0
- mkforge-0.1.0/src/mkforge/verification/rules/markdown/md034_bare_url.py +78 -0
- mkforge-0.1.0/src/mkforge/verification/rules/markdown/md035_horizontal_rule.py +49 -0
- mkforge-0.1.0/src/mkforge/verification/rules/markdown/md036_emphasis_heading.py +41 -0
- mkforge-0.1.0/src/mkforge/verification/rules/markdown/md037_emphasis_marker_space.py +38 -0
- mkforge-0.1.0/src/mkforge/verification/rules/markdown/md038_code_span_space.py +36 -0
- mkforge-0.1.0/src/mkforge/verification/rules/markdown/md039_link_text_space.py +36 -0
- mkforge-0.1.0/src/mkforge/verification/rules/markdown/md040_md041_md046_md047_blocks.py +134 -0
- mkforge-0.1.0/src/mkforge/verification/rules/markdown/mkf001_local_resource_exists.py +101 -0
- mkforge-0.1.0/src/mkforge/verification/settings.py +217 -0
- mkforge-0.1.0/src/mkforge/verification/source_scan.py +49 -0
- mkforge-0.1.0/tests/__init__.py +1 -0
- mkforge-0.1.0/tests/expectations.py +7 -0
- mkforge-0.1.0/tests/test_assets.py +509 -0
- mkforge-0.1.0/tests/test_e2e.py +1102 -0
- mkforge-0.1.0/tests/test_e2e_verification.py +530 -0
- mkforge-0.1.0/tests/test_helpers.py +39 -0
- mkforge-0.1.0/tests/test_markdown_validation.py +496 -0
- mkforge-0.1.0/tests/test_markdown_verification.py +481 -0
- mkforge-0.1.0/tests/test_metadata.py +14 -0
- mkforge-0.1.0/tests/test_report_generation.py +149 -0
- mkforge-0.1.0/tests/test_validation.py +178 -0
- mkforge-0.1.0/uv.lock +1304 -0
- mkforge-0.1.0/work/.gitkeep +1 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
pull_request:
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
check:
|
|
9
|
+
name: Lint · Type-check · Test
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
|
|
12
|
+
steps:
|
|
13
|
+
- name: Check out repository
|
|
14
|
+
uses: actions/checkout@v4
|
|
15
|
+
|
|
16
|
+
- name: Set up uv
|
|
17
|
+
uses: astral-sh/setup-uv@v5
|
|
18
|
+
with:
|
|
19
|
+
enable-cache: true
|
|
20
|
+
|
|
21
|
+
- name: Install dependencies
|
|
22
|
+
run: uv sync --group dev
|
|
23
|
+
|
|
24
|
+
- name: Run CI checks
|
|
25
|
+
run: make ci
|
|
26
|
+
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
name: Publish
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*"
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
build:
|
|
10
|
+
name: Build distributions
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
|
|
13
|
+
steps:
|
|
14
|
+
- name: Check out repository
|
|
15
|
+
uses: actions/checkout@v4
|
|
16
|
+
with:
|
|
17
|
+
fetch-depth: 0
|
|
18
|
+
|
|
19
|
+
- name: Ensure tag belongs to main
|
|
20
|
+
run: |
|
|
21
|
+
git fetch origin main
|
|
22
|
+
git merge-base --is-ancestor "$GITHUB_SHA" origin/main
|
|
23
|
+
|
|
24
|
+
- name: Set up uv
|
|
25
|
+
uses: astral-sh/setup-uv@v5
|
|
26
|
+
with:
|
|
27
|
+
enable-cache: true
|
|
28
|
+
|
|
29
|
+
- name: Install dependencies
|
|
30
|
+
run: uv sync --group dev
|
|
31
|
+
|
|
32
|
+
- name: Check tag matches package version
|
|
33
|
+
run: |
|
|
34
|
+
python - <<'PY'
|
|
35
|
+
import os
|
|
36
|
+
import tomllib
|
|
37
|
+
|
|
38
|
+
with open("pyproject.toml", "rb") as file:
|
|
39
|
+
version = tomllib.load(file)["project"]["version"]
|
|
40
|
+
|
|
41
|
+
tag = os.environ["GITHUB_REF_NAME"]
|
|
42
|
+
expected = f"v{version}"
|
|
43
|
+
if tag != expected:
|
|
44
|
+
raise SystemExit(f"Tag {tag} does not match package version {expected}")
|
|
45
|
+
PY
|
|
46
|
+
|
|
47
|
+
- name: Run checks
|
|
48
|
+
run: make ci
|
|
49
|
+
|
|
50
|
+
- name: Build distributions
|
|
51
|
+
run: uv build --out-dir work/dist
|
|
52
|
+
|
|
53
|
+
- name: Verify distributions
|
|
54
|
+
run: uv run twine check work/dist/*
|
|
55
|
+
|
|
56
|
+
- name: Upload distributions
|
|
57
|
+
uses: actions/upload-artifact@v4
|
|
58
|
+
with:
|
|
59
|
+
name: python-distributions
|
|
60
|
+
path: work/dist/
|
|
61
|
+
if-no-files-found: error
|
|
62
|
+
|
|
63
|
+
publish-pypi:
|
|
64
|
+
name: Publish to PyPI
|
|
65
|
+
needs: build
|
|
66
|
+
runs-on: ubuntu-latest
|
|
67
|
+
environment:
|
|
68
|
+
name: pypi
|
|
69
|
+
url: https://pypi.org/p/mkforge
|
|
70
|
+
permissions:
|
|
71
|
+
id-token: write
|
|
72
|
+
|
|
73
|
+
steps:
|
|
74
|
+
- name: Download distributions
|
|
75
|
+
uses: actions/download-artifact@v4
|
|
76
|
+
with:
|
|
77
|
+
name: python-distributions
|
|
78
|
+
path: dist/
|
|
79
|
+
|
|
80
|
+
- name: Publish to PyPI
|
|
81
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
82
|
+
|
mkforge-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# Virtual environments
|
|
7
|
+
.venv/
|
|
8
|
+
venv/
|
|
9
|
+
env/
|
|
10
|
+
ENV/
|
|
11
|
+
|
|
12
|
+
# Packaging
|
|
13
|
+
build/
|
|
14
|
+
dist/
|
|
15
|
+
*.egg-info/
|
|
16
|
+
.eggs/
|
|
17
|
+
|
|
18
|
+
# Test and coverage
|
|
19
|
+
.pytest_cache/
|
|
20
|
+
.coverage
|
|
21
|
+
.coverage.*
|
|
22
|
+
htmlcov/
|
|
23
|
+
|
|
24
|
+
# Type checkers and linters
|
|
25
|
+
.mypy_cache/
|
|
26
|
+
.ruff_cache/
|
|
27
|
+
.pyre/
|
|
28
|
+
.pytype/
|
|
29
|
+
|
|
30
|
+
# Editors and OS files
|
|
31
|
+
.DS_Store
|
|
32
|
+
.idea/
|
|
33
|
+
.vscode/
|
|
34
|
+
|
|
35
|
+
# Local workspace
|
|
36
|
+
work/*
|
|
37
|
+
!work/.gitkeep
|
|
38
|
+
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
image: python:3.12-slim
|
|
2
|
+
|
|
3
|
+
stages:
|
|
4
|
+
- check
|
|
5
|
+
- publish
|
|
6
|
+
|
|
7
|
+
workflow:
|
|
8
|
+
rules:
|
|
9
|
+
- if: $CI_COMMIT_TAG
|
|
10
|
+
- if: $CI_MERGE_REQUEST_IID
|
|
11
|
+
- if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS
|
|
12
|
+
when: never
|
|
13
|
+
- if: $CI_COMMIT_BRANCH
|
|
14
|
+
|
|
15
|
+
variables:
|
|
16
|
+
UV_CACHE_DIR: "$CI_PROJECT_DIR/.cache/uv"
|
|
17
|
+
|
|
18
|
+
cache:
|
|
19
|
+
key: "$CI_COMMIT_REF_SLUG"
|
|
20
|
+
paths:
|
|
21
|
+
- .cache/uv
|
|
22
|
+
|
|
23
|
+
before_script:
|
|
24
|
+
- apt-get update -qq && apt-get install -y -qq make
|
|
25
|
+
- pip install uv --quiet
|
|
26
|
+
- uv sync --group dev
|
|
27
|
+
|
|
28
|
+
check:
|
|
29
|
+
stage: check
|
|
30
|
+
script:
|
|
31
|
+
- make ci
|
|
32
|
+
|
|
33
|
+
publish-pypi:
|
|
34
|
+
stage: publish
|
|
35
|
+
rules:
|
|
36
|
+
- if: $CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+.*$/
|
|
37
|
+
script:
|
|
38
|
+
- |
|
|
39
|
+
python - <<'PY'
|
|
40
|
+
import os
|
|
41
|
+
import tomllib
|
|
42
|
+
|
|
43
|
+
with open("pyproject.toml", "rb") as file:
|
|
44
|
+
version = tomllib.load(file)["project"]["version"]
|
|
45
|
+
|
|
46
|
+
tag = os.environ["CI_COMMIT_TAG"]
|
|
47
|
+
expected = f"v{version}"
|
|
48
|
+
if tag != expected:
|
|
49
|
+
raise SystemExit(f"Tag {tag} does not match package version {expected}")
|
|
50
|
+
PY
|
|
51
|
+
- make ci
|
|
52
|
+
- uv build --out-dir work/dist
|
|
53
|
+
- uv run twine check work/dist/*
|
|
54
|
+
- uv run twine upload work/dist/*
|
|
55
|
+
|
mkforge-0.1.0/.mkforge
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
[verification]
|
|
2
|
+
disabled = []
|
|
3
|
+
|
|
4
|
+
[verification.rules.MD001]
|
|
5
|
+
front_matter_title = "^\\s*title\\s*[:=]"
|
|
6
|
+
|
|
7
|
+
[verification.rules.MD002]
|
|
8
|
+
level = 1
|
|
9
|
+
front_matter_title = "^\\s*title\\s*[:=]"
|
|
10
|
+
|
|
11
|
+
[verification.rules.MD003]
|
|
12
|
+
style = "consistent"
|
|
13
|
+
|
|
14
|
+
[verification.rules.MD004]
|
|
15
|
+
style = "consistent"
|
|
16
|
+
|
|
17
|
+
[verification.rules.MD007]
|
|
18
|
+
indent = 3
|
|
19
|
+
|
|
20
|
+
[verification.rules.MD009]
|
|
21
|
+
br_spaces = 2
|
|
22
|
+
|
|
23
|
+
[verification.rules.MD010]
|
|
24
|
+
ignore_code_blocks = false
|
|
25
|
+
|
|
26
|
+
[verification.rules.MD013]
|
|
27
|
+
line_length = 80
|
|
28
|
+
ignore_code_blocks = false
|
|
29
|
+
code_blocks = true
|
|
30
|
+
tables = true
|
|
31
|
+
headings = true
|
|
32
|
+
treat_links_as_single_words = false
|
|
33
|
+
|
|
34
|
+
[verification.rules.MD024]
|
|
35
|
+
allow_different_nesting = false
|
|
36
|
+
|
|
37
|
+
[verification.rules.MD025]
|
|
38
|
+
level = 1
|
|
39
|
+
front_matter_title = "^\\s*title\\s*[:=]"
|
|
40
|
+
|
|
41
|
+
[verification.rules.MD026]
|
|
42
|
+
punctuation = ".,;:!?"
|
|
43
|
+
|
|
44
|
+
[verification.rules.MD029]
|
|
45
|
+
style = "one"
|
|
46
|
+
|
|
47
|
+
[verification.rules.MD030]
|
|
48
|
+
ul_single = 1
|
|
49
|
+
ol_single = 1
|
|
50
|
+
ul_multi = 1
|
|
51
|
+
ol_multi = 1
|
|
52
|
+
|
|
53
|
+
[verification.rules.MD033]
|
|
54
|
+
allowed_elements = ""
|
|
55
|
+
|
|
56
|
+
[verification.rules.MD035]
|
|
57
|
+
style = "consistent"
|
|
58
|
+
|
|
59
|
+
[verification.rules.MD036]
|
|
60
|
+
punctuation = ".,;:!?"
|
|
61
|
+
|
|
62
|
+
[verification.rules.MD041]
|
|
63
|
+
level = 1
|
|
64
|
+
front_matter_title = "^\\s*title\\s*[:=]"
|
|
65
|
+
|
|
66
|
+
[verification.rules.MD046]
|
|
67
|
+
style = "fenced"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.12
|
mkforge-0.1.0/AGENTS.md
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# Codex Instructions
|
|
2
|
+
|
|
3
|
+
These instructions apply to the whole repository.
|
|
4
|
+
|
|
5
|
+
## Coding Standards
|
|
6
|
+
|
|
7
|
+
- Write Python code that strictly follows Python PEP rules and the Google
|
|
8
|
+
Python Style Guide.
|
|
9
|
+
- Keep each function small and focused.
|
|
10
|
+
- Keep cyclomatic complexity at or below 10 for every function.
|
|
11
|
+
- Keep Python modules below 500 lines unless an ADR explicitly justifies a
|
|
12
|
+
larger module.
|
|
13
|
+
- Do not optimize for maintainability-index scores when they encourage
|
|
14
|
+
artificial fragmentation into very small files.
|
|
15
|
+
- Write Google-style docstrings for every function and class, including private
|
|
16
|
+
functions and classes.
|
|
17
|
+
- Prefer explicit, readable, auditable code over clever abstractions.
|
|
18
|
+
- Use clear names and simple control flow.
|
|
19
|
+
- Add comments only when they clarify non-obvious intent or constraints.
|
|
20
|
+
- Apply SOLID principles strictly:
|
|
21
|
+
- Single Responsibility: each module, class, and function must have one clear
|
|
22
|
+
reason to change.
|
|
23
|
+
- Open/Closed: add behavior through new focused implementations, rules,
|
|
24
|
+
strategies, or registries instead of editing large conditional blocks.
|
|
25
|
+
- Liskov Substitution: implementations of a public protocol must remain
|
|
26
|
+
interchangeable and must not weaken expected behavior.
|
|
27
|
+
- Interface Segregation: depend on narrow protocols or callables rather than
|
|
28
|
+
broad objects with unrelated responsibilities.
|
|
29
|
+
- Dependency Inversion: high-level workflows depend on stable interfaces, not
|
|
30
|
+
concrete low-level details.
|
|
31
|
+
|
|
32
|
+
## Dependencies
|
|
33
|
+
|
|
34
|
+
- Minimize external dependencies.
|
|
35
|
+
- Prefer the Python standard library by default.
|
|
36
|
+
- Add third-party packages only when explicitly requested or when the standard
|
|
37
|
+
library is clearly insufficient for the task.
|
|
38
|
+
- Before adding a dependency, document why it is needed.
|
|
39
|
+
|
|
40
|
+
## Design
|
|
41
|
+
|
|
42
|
+
- Start substantial feature work and architecture changes with an Architecture
|
|
43
|
+
Decision Record before implementing code.
|
|
44
|
+
- Include PlantUML diagrams in ADRs when they clarify structure, behavior,
|
|
45
|
+
dependencies, lifecycles, or integration flows.
|
|
46
|
+
- Document the design patterns used in each ADR, including why each pattern is
|
|
47
|
+
appropriate and what tradeoff it introduces.
|
|
48
|
+
- Define public APIs, internal interfaces, data contracts, and expected error
|
|
49
|
+
behavior in the ADR before filling in feature implementation details.
|
|
50
|
+
- Implement features only after the architecture, API boundaries, and extension
|
|
51
|
+
points are explicit enough to review.
|
|
52
|
+
- Prefer a clean package layout over compatibility with unpublished APIs.
|
|
53
|
+
- Name modules, classes, functions, variables, and tests with business/domain
|
|
54
|
+
vocabulary first. Prefer names such as `verify_file`, `heading_slugs`, or
|
|
55
|
+
`required_headings` over architecture-first names such as `node`, `leaf`,
|
|
56
|
+
`manager`, `processor`, `handler`, `orchestrator`, or `service` unless those
|
|
57
|
+
words are the real domain concept.
|
|
58
|
+
- Prefer concrete, short, auditable names over abstract framework names.
|
|
59
|
+
- Keep public APIs narrow and stable.
|
|
60
|
+
- Avoid hidden side effects.
|
|
61
|
+
- Prefer pure functions for transformation logic.
|
|
62
|
+
- Validate inputs close to the boundary of the system.
|
|
63
|
+
- Make error messages precise and useful.
|
|
64
|
+
- Use design patterns deliberately to improve maintainability and evolvability:
|
|
65
|
+
- use Strategy when behavior varies by profile, format, rule, or policy;
|
|
66
|
+
- use Registry when behavior must be extended without modifying the engine;
|
|
67
|
+
- use Adapter when exposing a simple callable or external API behind an
|
|
68
|
+
internal interface;
|
|
69
|
+
- use Factory functions when object creation has validation or multiple
|
|
70
|
+
variants;
|
|
71
|
+
- use Template Method only when a workflow is stable and extension points are
|
|
72
|
+
explicit.
|
|
73
|
+
- Do not introduce a design pattern for decoration. A pattern is acceptable only
|
|
74
|
+
when it removes duplication, reduces conditional complexity, clarifies an
|
|
75
|
+
extension point, or protects a public contract.
|
|
76
|
+
- Separate verification from validation:
|
|
77
|
+
- verification checks Markdown or GitHub Flavored Markdown conformance;
|
|
78
|
+
- validation checks document content, metadata, required headings, wording,
|
|
79
|
+
and project-specific policies.
|
|
80
|
+
- Keep diagnostics auditable: one diagnostic rule must live in one Python
|
|
81
|
+
module, grouped under the relevant `verification/` or `validation/`
|
|
82
|
+
package, and the module docstring must explain precisely what the rule
|
|
83
|
+
checks.
|
|
84
|
+
- Avoid Python files that only re-export imports. A module must own behavior,
|
|
85
|
+
data, or documentation that justifies its existence.
|
|
86
|
+
|
|
87
|
+
## Tests and Documentation
|
|
88
|
+
|
|
89
|
+
- Maintain 100% test coverage.
|
|
90
|
+
- Write tests for all new behavior.
|
|
91
|
+
- For new public behavior, add targeted validation tests for construction and
|
|
92
|
+
input contracts, targeted verification tests for rendered Markdown or GFM
|
|
93
|
+
conformance when applicable, and end-to-end tests only as workflow coverage;
|
|
94
|
+
do not rely on end-to-end tests alone.
|
|
95
|
+
- Test function docstrings must state the requirement being verified.
|
|
96
|
+
- Every module, function, class, method, and test must include a strict
|
|
97
|
+
Google-style docstring, including private functions and classes.
|
|
98
|
+
- Function and method docstrings must include:
|
|
99
|
+
- a precise summary that explains the domain behavior;
|
|
100
|
+
- `Args:` for every parameter except `self` and `cls`;
|
|
101
|
+
- `Returns:` for every non-`None` return value;
|
|
102
|
+
- `Raises:` for every intentionally raised exception.
|
|
103
|
+
- Class docstrings must include `Attributes:` when instances expose public
|
|
104
|
+
attributes.
|
|
105
|
+
- Module docstrings for diagnostic rules must explain what the rule checks, why
|
|
106
|
+
it belongs to verification or validation, and what kind of diagnostic it
|
|
107
|
+
emits.
|
|
108
|
+
- Avoid placeholder docstrings such as `Function result.`, vague summaries, or a
|
|
109
|
+
single imperative sentence that does not document inputs and outputs.
|
|
110
|
+
|
|
111
|
+
## Quality Checks
|
|
112
|
+
|
|
113
|
+
Run these checks before considering code complete:
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
make check
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Use `make ci` for non-mutating verification and `make check-dist` before
|
|
120
|
+
publishing.
|
mkforge-0.1.0/CLAUDE.md
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
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. Validation helpers that are only
|
|
15
|
+
ever used by one module belong in that module, not in a separate file.
|
|
16
|
+
- Do not optimize for maintainability-index scores when they encourage
|
|
17
|
+
artificial fragmentation into very small files.
|
|
18
|
+
- Write Google-style docstrings for every function and class, including private
|
|
19
|
+
functions and classes.
|
|
20
|
+
- Write clean, auditable code with simple control flow.
|
|
21
|
+
- Favor clarity over cleverness.
|
|
22
|
+
- Use precise names for modules, classes, functions, variables, and tests.
|
|
23
|
+
- Keep comments rare and useful.
|
|
24
|
+
- Apply SOLID principles strictly:
|
|
25
|
+
- Single Responsibility: each module, class, and function must have one clear
|
|
26
|
+
reason to change.
|
|
27
|
+
- Open/Closed: add behavior through new focused implementations, rules,
|
|
28
|
+
strategies, or registries instead of editing large conditional blocks.
|
|
29
|
+
- Liskov Substitution: implementations of a public protocol must remain
|
|
30
|
+
interchangeable and must not weaken expected behavior.
|
|
31
|
+
- Interface Segregation: depend on narrow protocols or callables rather than
|
|
32
|
+
broad objects with unrelated responsibilities.
|
|
33
|
+
- Dependency Inversion: high-level workflows depend on stable interfaces, not
|
|
34
|
+
concrete low-level details.
|
|
35
|
+
|
|
36
|
+
## Dependencies
|
|
37
|
+
|
|
38
|
+
- Minimize external dependencies.
|
|
39
|
+
- Prefer Python standard library packages.
|
|
40
|
+
- Do not add third-party dependencies unless explicitly requested by the user or
|
|
41
|
+
unless there is a clear technical need that cannot reasonably be met with the
|
|
42
|
+
standard library.
|
|
43
|
+
- Explain the reason for any new dependency before adding it.
|
|
44
|
+
|
|
45
|
+
## Implementation Guidance
|
|
46
|
+
|
|
47
|
+
- Start substantial feature work and architecture changes with an Architecture
|
|
48
|
+
Decision Record before implementing code.
|
|
49
|
+
- Include PlantUML diagrams in ADRs when they clarify structure, behavior,
|
|
50
|
+
dependencies, lifecycles, or integration flows.
|
|
51
|
+
- Document the design patterns used in each ADR, including why each pattern is
|
|
52
|
+
appropriate and what tradeoff it introduces.
|
|
53
|
+
- Define public APIs, internal interfaces, data contracts, and expected error
|
|
54
|
+
behavior in the ADR before filling in feature implementation details.
|
|
55
|
+
- Implement features only after the architecture, API boundaries, and extension
|
|
56
|
+
points are explicit enough to review.
|
|
57
|
+
- Keep changes focused on the requested behavior.
|
|
58
|
+
- Keep public interfaces small.
|
|
59
|
+
- Name modules, classes, functions, variables, and tests with business/domain
|
|
60
|
+
vocabulary first. Prefer names such as `verify_file`, `heading_slugs`, or
|
|
61
|
+
`required_headings` over architecture-first names such as `node`, `leaf`,
|
|
62
|
+
`manager`, `processor`, `handler`, `orchestrator`, or `service` unless those
|
|
63
|
+
words are the real domain concept.
|
|
64
|
+
- Prefer concrete, short, auditable names over abstract framework names.
|
|
65
|
+
- Avoid global mutable state unless there is a clear reason.
|
|
66
|
+
- Prefer deterministic behavior and explicit inputs.
|
|
67
|
+
- Use design patterns deliberately to improve maintainability and evolvability:
|
|
68
|
+
- use Strategy when behavior varies by profile, format, rule, or policy;
|
|
69
|
+
- use Registry when behavior must be extended without modifying the engine;
|
|
70
|
+
- use Adapter when exposing a simple callable or external API behind an
|
|
71
|
+
internal interface;
|
|
72
|
+
- use Factory functions when object creation has validation or multiple
|
|
73
|
+
variants;
|
|
74
|
+
- use Template Method only when a workflow is stable and extension points are
|
|
75
|
+
explicit.
|
|
76
|
+
- Do not introduce a design pattern for decoration. A pattern is acceptable only
|
|
77
|
+
when it removes duplication, reduces conditional complexity, clarifies an
|
|
78
|
+
extension point, or protects a public contract.
|
|
79
|
+
- Keep diagnostics auditable: one diagnostic rule must live in one Python
|
|
80
|
+
module, grouped under the relevant `verification/` or `validation/`
|
|
81
|
+
package, and the module docstring must explain precisely what the rule
|
|
82
|
+
checks.
|
|
83
|
+
- Avoid Python files that only re-export imports. A module must own behavior,
|
|
84
|
+
data, or documentation that justifies its existence.
|
|
85
|
+
- Group code by business cohesion, not by technical layer. Content element
|
|
86
|
+
types and their construction-time validation belong together. Rendering
|
|
87
|
+
logic for all element types belongs in one rendering module. Do not create
|
|
88
|
+
separate ``*_validation.py``, ``*_rendering.py``, or ``*_helpers.py``
|
|
89
|
+
satellites when the behavior is inseparable from its host module.
|
|
90
|
+
- Write tests for new behavior.
|
|
91
|
+
- For new public behavior, add targeted validation tests for construction and
|
|
92
|
+
input contracts, targeted verification tests for rendered Markdown or GFM
|
|
93
|
+
conformance when applicable, and end-to-end tests only as workflow coverage;
|
|
94
|
+
do not rely on end-to-end tests alone.
|
|
95
|
+
- Maintain 100% test coverage.
|
|
96
|
+
- Test function docstrings must state the requirement being verified.
|
|
97
|
+
- Every module, function, class, method, and test must include a strict
|
|
98
|
+
Google-style docstring, including private functions and classes.
|
|
99
|
+
- Function and method docstrings must include:
|
|
100
|
+
- a precise summary that explains the domain behavior;
|
|
101
|
+
- `Args:` for every parameter except `self` and `cls`;
|
|
102
|
+
- `Returns:` for every non-`None` return value;
|
|
103
|
+
- `Raises:` for every intentionally raised exception.
|
|
104
|
+
- Class docstrings must include `Attributes:` when instances expose public
|
|
105
|
+
attributes.
|
|
106
|
+
- Module docstrings for diagnostic rules must explain what the rule checks, why
|
|
107
|
+
it belongs to verification or validation, and what kind of diagnostic it
|
|
108
|
+
emits.
|
|
109
|
+
- Avoid placeholder docstrings such as `Function result.`, vague summaries, or a
|
|
110
|
+
single imperative sentence that does not document inputs and outputs.
|
|
111
|
+
|
|
112
|
+
## Quality Checks
|
|
113
|
+
|
|
114
|
+
Before finishing code changes, run:
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
make check
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Use `make ci` for non-mutating verification and `make check-dist` before
|
|
121
|
+
publishing.
|
mkforge-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Antoine Barré
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
mkforge-0.1.0/Makefile
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
.PHONY: clean clean-work format format-check lint flake8 docstrings typecheck metrics security test check ci build check-dist publish-test publish
|
|
2
|
+
|
|
3
|
+
PYTHON_FILES := src tests scripts
|
|
4
|
+
|
|
5
|
+
clean-work:
|
|
6
|
+
@mkdir -p work
|
|
7
|
+
@find work -mindepth 1 ! -name .gitkeep -exec rm -rf {} +
|
|
8
|
+
|
|
9
|
+
clean: clean-work
|
|
10
|
+
|
|
11
|
+
format format-check lint flake8 docstrings typecheck metrics security test check ci build check-dist publish-test publish: clean-work
|
|
12
|
+
|
|
13
|
+
format:
|
|
14
|
+
@uv run ruff format $(PYTHON_FILES)
|
|
15
|
+
|
|
16
|
+
format-check:
|
|
17
|
+
@uv run ruff format --check $(PYTHON_FILES)
|
|
18
|
+
|
|
19
|
+
lint:
|
|
20
|
+
@uv run ruff check $(PYTHON_FILES)
|
|
21
|
+
|
|
22
|
+
flake8:
|
|
23
|
+
@uv run flake8 $(PYTHON_FILES)
|
|
24
|
+
|
|
25
|
+
docstrings:
|
|
26
|
+
@uv run python scripts/check_docstrings.py
|
|
27
|
+
|
|
28
|
+
typecheck:
|
|
29
|
+
@uv run mypy src tests scripts
|
|
30
|
+
|
|
31
|
+
metrics:
|
|
32
|
+
@uv run python scripts/code_metrics.py
|
|
33
|
+
|
|
34
|
+
security:
|
|
35
|
+
@uv run bandit -c pyproject.toml -r src scripts
|
|
36
|
+
@bash scripts/security_deps.sh
|
|
37
|
+
|
|
38
|
+
test:
|
|
39
|
+
@uv run pytest
|
|
40
|
+
|
|
41
|
+
check:
|
|
42
|
+
@bash scripts/check.sh
|
|
43
|
+
|
|
44
|
+
ci:
|
|
45
|
+
@bash scripts/check.sh --ci
|
|
46
|
+
|
|
47
|
+
build:
|
|
48
|
+
@bash scripts/publish.sh build
|
|
49
|
+
|
|
50
|
+
check-dist:
|
|
51
|
+
@bash scripts/publish.sh check-dist
|
|
52
|
+
|
|
53
|
+
publish-test:
|
|
54
|
+
@bash scripts/publish.sh publish-test
|
|
55
|
+
|
|
56
|
+
publish:
|
|
57
|
+
@bash scripts/publish.sh publish
|