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.
Files changed (108) hide show
  1. mkforge-0.1.0/.github/workflows/ci.yml +26 -0
  2. mkforge-0.1.0/.github/workflows/publish.yml +82 -0
  3. mkforge-0.1.0/.gitignore +38 -0
  4. mkforge-0.1.0/.gitlab-ci.yml +55 -0
  5. mkforge-0.1.0/.mkforge +67 -0
  6. mkforge-0.1.0/.python-version +1 -0
  7. mkforge-0.1.0/AGENTS.md +120 -0
  8. mkforge-0.1.0/CLAUDE.md +121 -0
  9. mkforge-0.1.0/LICENSE +22 -0
  10. mkforge-0.1.0/Makefile +57 -0
  11. mkforge-0.1.0/PKG-INFO +158 -0
  12. mkforge-0.1.0/README.md +143 -0
  13. mkforge-0.1.0/demo_report.py +235 -0
  14. mkforge-0.1.0/demo_validation.py +291 -0
  15. mkforge-0.1.0/demo_verif.py +236 -0
  16. mkforge-0.1.0/doc/adr-001-markdown-conformance-verifier.md +197 -0
  17. mkforge-0.1.0/docs/API_REFERENCE.md +1724 -0
  18. mkforge-0.1.0/docs/MARKDOWN_RULES.md +958 -0
  19. mkforge-0.1.0/docs/SDD.md +902 -0
  20. mkforge-0.1.0/docs/SRS.md +550 -0
  21. mkforge-0.1.0/docs/USER_GUIDE.md +1053 -0
  22. mkforge-0.1.0/docs/adr/ADR-001-asset-management.md +142 -0
  23. mkforge-0.1.0/docs/adr/ADR-002-markdown-validation-contracts.md +98 -0
  24. mkforge-0.1.0/docs/pypi-publication.md +70 -0
  25. mkforge-0.1.0/main.py +6 -0
  26. mkforge-0.1.0/pyproject.toml +98 -0
  27. mkforge-0.1.0/scripts/__init__.py +1 -0
  28. mkforge-0.1.0/scripts/check.sh +120 -0
  29. mkforge-0.1.0/scripts/check_docstrings.py +129 -0
  30. mkforge-0.1.0/scripts/code_metrics.py +397 -0
  31. mkforge-0.1.0/scripts/publish.sh +31 -0
  32. mkforge-0.1.0/scripts/security_deps.sh +13 -0
  33. mkforge-0.1.0/src/mkforge/__init__.py +76 -0
  34. mkforge-0.1.0/src/mkforge/_metadata.py +4 -0
  35. mkforge-0.1.0/src/mkforge/assets.py +387 -0
  36. mkforge-0.1.0/src/mkforge/content/__init__.py +62 -0
  37. mkforge-0.1.0/src/mkforge/content/_base.py +26 -0
  38. mkforge-0.1.0/src/mkforge/content/code.py +39 -0
  39. mkforge-0.1.0/src/mkforge/content/image.py +42 -0
  40. mkforge-0.1.0/src/mkforge/content/lists.py +80 -0
  41. mkforge-0.1.0/src/mkforge/content/misc.py +47 -0
  42. mkforge-0.1.0/src/mkforge/content/paragraph.py +70 -0
  43. mkforge-0.1.0/src/mkforge/content/table.py +161 -0
  44. mkforge-0.1.0/src/mkforge/content/text.py +118 -0
  45. mkforge-0.1.0/src/mkforge/document.py +314 -0
  46. mkforge-0.1.0/src/mkforge/errors.py +88 -0
  47. mkforge-0.1.0/src/mkforge/input_checks.py +93 -0
  48. mkforge-0.1.0/src/mkforge/py.typed +1 -0
  49. mkforge-0.1.0/src/mkforge/rendering.py +513 -0
  50. mkforge-0.1.0/src/mkforge/validation/__init__.py +21 -0
  51. mkforge-0.1.0/src/mkforge/validation/markdown_contracts.py +667 -0
  52. mkforge-0.1.0/src/mkforge/verification/__init__.py +25 -0
  53. mkforge-0.1.0/src/mkforge/verification/api.py +134 -0
  54. mkforge-0.1.0/src/mkforge/verification/diagnostic_pattern.py +41 -0
  55. mkforge-0.1.0/src/mkforge/verification/policy.py +121 -0
  56. mkforge-0.1.0/src/mkforge/verification/registry.py +76 -0
  57. mkforge-0.1.0/src/mkforge/verification/rules/__init__.py +1 -0
  58. mkforge-0.1.0/src/mkforge/verification/rules/gfm/__init__.py +1 -0
  59. mkforge-0.1.0/src/mkforge/verification/rules/gfm/gfm001_table_delimiter.py +97 -0
  60. mkforge-0.1.0/src/mkforge/verification/rules/gfm/gfm002_table_column_count.py +132 -0
  61. mkforge-0.1.0/src/mkforge/verification/rules/gfm/gfm003_task_list_marker.py +52 -0
  62. mkforge-0.1.0/src/mkforge/verification/rules/markdown/__init__.py +1 -0
  63. mkforge-0.1.0/src/mkforge/verification/rules/markdown/_shared.py +607 -0
  64. mkforge-0.1.0/src/mkforge/verification/rules/markdown/markdownlint_remaining.py +139 -0
  65. mkforge-0.1.0/src/mkforge/verification/rules/markdown/md001_heading_increment.py +36 -0
  66. mkforge-0.1.0/src/mkforge/verification/rules/markdown/md002_first_heading_level.py +42 -0
  67. mkforge-0.1.0/src/mkforge/verification/rules/markdown/md003_heading_style.py +40 -0
  68. mkforge-0.1.0/src/mkforge/verification/rules/markdown/md004_unordered_list_style.py +43 -0
  69. mkforge-0.1.0/src/mkforge/verification/rules/markdown/md005_md006_md007_list_indentation.py +112 -0
  70. mkforge-0.1.0/src/mkforge/verification/rules/markdown/md009_trailing_spaces.py +40 -0
  71. mkforge-0.1.0/src/mkforge/verification/rules/markdown/md010_hard_tabs.py +37 -0
  72. mkforge-0.1.0/src/mkforge/verification/rules/markdown/md011_reversed_link_syntax.py +36 -0
  73. mkforge-0.1.0/src/mkforge/verification/rules/markdown/md012_multiple_blank_lines.py +38 -0
  74. mkforge-0.1.0/src/mkforge/verification/rules/markdown/md013_line_length.py +40 -0
  75. mkforge-0.1.0/src/mkforge/verification/rules/markdown/md014_command_prompt.py +42 -0
  76. mkforge-0.1.0/src/mkforge/verification/rules/markdown/md018_atx_heading_space.py +36 -0
  77. mkforge-0.1.0/src/mkforge/verification/rules/markdown/md019_md021_atx_closed_spaces.py +81 -0
  78. mkforge-0.1.0/src/mkforge/verification/rules/markdown/md020_closed_atx_heading_space.py +39 -0
  79. mkforge-0.1.0/src/mkforge/verification/rules/markdown/md022_md023_heading_blanks.py +85 -0
  80. mkforge-0.1.0/src/mkforge/verification/rules/markdown/md024_md025_duplicate_headings.py +84 -0
  81. mkforge-0.1.0/src/mkforge/verification/rules/markdown/md026_heading_punctuation.py +36 -0
  82. mkforge-0.1.0/src/mkforge/verification/rules/markdown/md027_md028_blockquote.py +78 -0
  83. mkforge-0.1.0/src/mkforge/verification/rules/markdown/md029_md030_list_prefix.py +87 -0
  84. mkforge-0.1.0/src/mkforge/verification/rules/markdown/md031_md032_fence_list_blanks.py +100 -0
  85. mkforge-0.1.0/src/mkforge/verification/rules/markdown/md033_inline_html.py +41 -0
  86. mkforge-0.1.0/src/mkforge/verification/rules/markdown/md034_bare_url.py +78 -0
  87. mkforge-0.1.0/src/mkforge/verification/rules/markdown/md035_horizontal_rule.py +49 -0
  88. mkforge-0.1.0/src/mkforge/verification/rules/markdown/md036_emphasis_heading.py +41 -0
  89. mkforge-0.1.0/src/mkforge/verification/rules/markdown/md037_emphasis_marker_space.py +38 -0
  90. mkforge-0.1.0/src/mkforge/verification/rules/markdown/md038_code_span_space.py +36 -0
  91. mkforge-0.1.0/src/mkforge/verification/rules/markdown/md039_link_text_space.py +36 -0
  92. mkforge-0.1.0/src/mkforge/verification/rules/markdown/md040_md041_md046_md047_blocks.py +134 -0
  93. mkforge-0.1.0/src/mkforge/verification/rules/markdown/mkf001_local_resource_exists.py +101 -0
  94. mkforge-0.1.0/src/mkforge/verification/settings.py +217 -0
  95. mkforge-0.1.0/src/mkforge/verification/source_scan.py +49 -0
  96. mkforge-0.1.0/tests/__init__.py +1 -0
  97. mkforge-0.1.0/tests/expectations.py +7 -0
  98. mkforge-0.1.0/tests/test_assets.py +509 -0
  99. mkforge-0.1.0/tests/test_e2e.py +1102 -0
  100. mkforge-0.1.0/tests/test_e2e_verification.py +530 -0
  101. mkforge-0.1.0/tests/test_helpers.py +39 -0
  102. mkforge-0.1.0/tests/test_markdown_validation.py +496 -0
  103. mkforge-0.1.0/tests/test_markdown_verification.py +481 -0
  104. mkforge-0.1.0/tests/test_metadata.py +14 -0
  105. mkforge-0.1.0/tests/test_report_generation.py +149 -0
  106. mkforge-0.1.0/tests/test_validation.py +178 -0
  107. mkforge-0.1.0/uv.lock +1304 -0
  108. 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
+
@@ -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
@@ -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.
@@ -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