h2h-dev-tools 0.2.1__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 (68) hide show
  1. h2h_dev_tools-0.2.1/.githooks/commit-msg +18 -0
  2. h2h_dev_tools-0.2.1/.githooks/pre-commit +21 -0
  3. h2h_dev_tools-0.2.1/.githooks/pre-merge-commit +9 -0
  4. h2h_dev_tools-0.2.1/.githooks/pre-rebase +16 -0
  5. h2h_dev_tools-0.2.1/.github/workflows/publish.yml +70 -0
  6. h2h_dev_tools-0.2.1/.github/workflows/windows-process.yml +31 -0
  7. h2h_dev_tools-0.2.1/.gitignore +15 -0
  8. h2h_dev_tools-0.2.1/.markdownlint-cli2.jsonc +25 -0
  9. h2h_dev_tools-0.2.1/.release/dependency-audit.json +98 -0
  10. h2h_dev_tools-0.2.1/AGENTS.md +109 -0
  11. h2h_dev_tools-0.2.1/LICENSE +674 -0
  12. h2h_dev_tools-0.2.1/PKG-INFO +221 -0
  13. h2h_dev_tools-0.2.1/README.md +197 -0
  14. h2h_dev_tools-0.2.1/package.json +11 -0
  15. h2h_dev_tools-0.2.1/pyproject.toml +80 -0
  16. h2h_dev_tools-0.2.1/scripts/audit-dependencies.py +10 -0
  17. h2h_dev_tools-0.2.1/scripts/build-and-verify-distributions.py +164 -0
  18. h2h_dev_tools-0.2.1/scripts/check-docs.py +9 -0
  19. h2h_dev_tools-0.2.1/scripts/check-fast.sh +13 -0
  20. h2h_dev_tools-0.2.1/scripts/check-full.sh +6 -0
  21. h2h_dev_tools-0.2.1/scripts/check-publish-version.py +9 -0
  22. h2h_dev_tools-0.2.1/scripts/check-version.py +10 -0
  23. h2h_dev_tools-0.2.1/scripts/check_change_scope.py +9 -0
  24. h2h_dev_tools-0.2.1/scripts/detect-primary-branch.sh +4 -0
  25. h2h_dev_tools-0.2.1/scripts/format.sh +6 -0
  26. h2h_dev_tools-0.2.1/scripts/git-flow-merge.sh +4 -0
  27. h2h_dev_tools-0.2.1/scripts/install-ci-dependencies.py +12 -0
  28. h2h_dev_tools-0.2.1/scripts/install-git-hooks.sh +4 -0
  29. h2h_dev_tools-0.2.1/scripts/rebuild-env.sh +4 -0
  30. h2h_dev_tools-0.2.1/scripts/release-gate.py +49 -0
  31. h2h_dev_tools-0.2.1/scripts/select-publish-version.py +57 -0
  32. h2h_dev_tools-0.2.1/src/h2h_dev_tools/__init__.py +1 -0
  33. h2h_dev_tools-0.2.1/src/h2h_dev_tools/__main__.py +43 -0
  34. h2h_dev_tools-0.2.1/src/h2h_dev_tools/atomic_files.py +32 -0
  35. h2h_dev_tools-0.2.1/src/h2h_dev_tools/bundle.py +107 -0
  36. h2h_dev_tools-0.2.1/src/h2h_dev_tools/bundle_verify.py +255 -0
  37. h2h_dev_tools-0.2.1/src/h2h_dev_tools/change_scope.py +167 -0
  38. h2h_dev_tools-0.2.1/src/h2h_dev_tools/ci_dependencies.py +70 -0
  39. h2h_dev_tools-0.2.1/src/h2h_dev_tools/dependency_audit.py +220 -0
  40. h2h_dev_tools-0.2.1/src/h2h_dev_tools/dependency_manifest.py +23 -0
  41. h2h_dev_tools-0.2.1/src/h2h_dev_tools/distribution_check.py +70 -0
  42. h2h_dev_tools-0.2.1/src/h2h_dev_tools/documentation.py +175 -0
  43. h2h_dev_tools-0.2.1/src/h2h_dev_tools/formal.py +209 -0
  44. h2h_dev_tools-0.2.1/src/h2h_dev_tools/git-flow-merge.sh +263 -0
  45. h2h_dev_tools-0.2.1/src/h2h_dev_tools/install-git-hooks.sh +34 -0
  46. h2h_dev_tools-0.2.1/src/h2h_dev_tools/migrate_v1.py +61 -0
  47. h2h_dev_tools-0.2.1/src/h2h_dev_tools/offline_wheel.py +138 -0
  48. h2h_dev_tools-0.2.1/src/h2h_dev_tools/primary-branch.sh +52 -0
  49. h2h_dev_tools-0.2.1/src/h2h_dev_tools/process.py +873 -0
  50. h2h_dev_tools-0.2.1/src/h2h_dev_tools/publish_version.py +106 -0
  51. h2h_dev_tools-0.2.1/src/h2h_dev_tools/rebuild-env.sh +80 -0
  52. h2h_dev_tools-0.2.1/src/h2h_dev_tools/version_policy.py +391 -0
  53. h2h_dev_tools-0.2.1/tests/test_atomic_files.py +73 -0
  54. h2h_dev_tools-0.2.1/tests/test_bootstrap.py +136 -0
  55. h2h_dev_tools-0.2.1/tests/test_bundle.py +504 -0
  56. h2h_dev_tools-0.2.1/tests/test_ci_dependencies.py +128 -0
  57. h2h_dev_tools-0.2.1/tests/test_dependency_audit.py +88 -0
  58. h2h_dev_tools-0.2.1/tests/test_dependency_manifest.py +51 -0
  59. h2h_dev_tools-0.2.1/tests/test_distribution_check.py +73 -0
  60. h2h_dev_tools-0.2.1/tests/test_documentation_checks.py +574 -0
  61. h2h_dev_tools-0.2.1/tests/test_formal.py +119 -0
  62. h2h_dev_tools-0.2.1/tests/test_merge_workflow.py +117 -0
  63. h2h_dev_tools-0.2.1/tests/test_offline_wheel.py +158 -0
  64. h2h_dev_tools-0.2.1/tests/test_process.py +943 -0
  65. h2h_dev_tools-0.2.1/tests/test_process_integration.py +169 -0
  66. h2h_dev_tools-0.2.1/tests/test_publish_selection.py +48 -0
  67. h2h_dev_tools-0.2.1/tests/test_publish_version.py +172 -0
  68. h2h_dev_tools-0.2.1/tests/test_release_policy.py +203 -0
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env bash
2
+
3
+ set -euo pipefail
4
+
5
+ message_file=$1
6
+ first_line="$(sed -n '1p' "$message_file")"
7
+
8
+ if [[ "$first_line" == Merge\ * ]] \
9
+ && git rev-parse --verify MERGE_HEAD >/dev/null 2>&1; then
10
+ exit 0
11
+ fi
12
+
13
+ pattern='^(build|chore|ci|docs|feat|fix|perf|refactor|revert|style|test)(\([a-z0-9._/-]+\))?(!)?: .+'
14
+ if [[ ! "$first_line" =~ $pattern ]]; then
15
+ printf 'Commit message must follow Conventional Commits: %s\n' \
16
+ "$first_line" >&2
17
+ exit 1
18
+ fi
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ cd "$(git rev-parse --show-toplevel)"
4
+ primary="$(scripts/detect-primary-branch.sh)"
5
+ if git rev-parse --verify MERGE_HEAD >/dev/null 2>&1; then
6
+ exec .githooks/pre-merge-commit
7
+ fi
8
+ [[ -n "$(git branch --show-current)" ]] || {
9
+ printf 'Commit requires a task branch, not detached HEAD\n' >&2
10
+ exit 1
11
+ }
12
+ [[ "$(git branch --show-current)" != "$primary" ]] || {
13
+ printf 'Direct commits on primary are not allowed: %s\n' "$primary" >&2
14
+ exit 1
15
+ }
16
+ profile="$(.venv/bin/python scripts/check_change_scope.py --index --base HEAD)"
17
+ case "$profile" in
18
+ documentation) exec .venv/bin/python scripts/check-docs.py --index --base HEAD ;;
19
+ full) exec scripts/check-fast.sh ;;
20
+ *) printf 'Unknown check profile: %s\n' "$profile" >&2; exit 1 ;;
21
+ esac
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ cd "$(git rev-parse --show-toplevel)"
4
+ primary="$(scripts/detect-primary-branch.sh)"
5
+ [[ "$(git branch --show-current)" == "$primary" ]] || {
6
+ printf 'Merge commits are permitted only on primary: %s\n' "$primary" >&2
7
+ exit 1
8
+ }
9
+ exec .venv/bin/python scripts/release-gate.py
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env bash
2
+
3
+ set -euo pipefail
4
+
5
+ repository_root="$(git rev-parse --show-toplevel)"
6
+ cd "$repository_root"
7
+
8
+ primary="$(scripts/detect-primary-branch.sh)"
9
+ rebased_branch="${2:-$(git symbolic-ref --quiet HEAD || true)}"
10
+ rebased_branch="${rebased_branch#refs/heads/}"
11
+
12
+ if [[ "$rebased_branch" == "$primary" ]]; then
13
+ printf 'Rebasing primary is not allowed: %s; preserve merge history.\n' \
14
+ "$primary" >&2
15
+ exit 1
16
+ fi
@@ -0,0 +1,70 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ push:
5
+ paths:
6
+ - pyproject.toml
7
+ workflow_dispatch:
8
+ inputs:
9
+ version:
10
+ description: Exact project version to publish, including the first release
11
+ required: true
12
+ type: string
13
+
14
+ permissions:
15
+ contents: read
16
+
17
+ jobs:
18
+ validate:
19
+ if: >-
20
+ ${{ github.ref ==
21
+ format('refs/heads/{0}', github.event.repository.default_branch) }}
22
+ runs-on: ubuntu-latest
23
+ timeout-minutes: 10
24
+ outputs:
25
+ publish: ${{ steps.version.outputs.publish }}
26
+ steps:
27
+ - uses: actions/checkout@v4
28
+ with:
29
+ fetch-depth: 2
30
+ - uses: actions/setup-python@v5
31
+ with:
32
+ python-version: "3.14"
33
+ - name: Install declared build dependencies
34
+ run: |
35
+ python scripts/install-ci-dependencies.py packaging build hatchling
36
+ - name: Select explicitly requested version or push transition
37
+ id: version
38
+ env:
39
+ BEFORE_SHA: ${{ github.event.before }}
40
+ REQUESTED_VERSION: ${{ inputs.version }}
41
+ EVENT_NAME: ${{ github.event_name }}
42
+ run: python scripts/select-publish-version.py
43
+ - name: Build and verify distributions
44
+ if: steps.version.outputs.publish == 'true'
45
+ run: >-
46
+ python scripts/build-and-verify-distributions.py
47
+ --output-directory dist
48
+ - name: Store distributions
49
+ if: steps.version.outputs.publish == 'true'
50
+ uses: actions/upload-artifact@v4
51
+ with:
52
+ name: distributions
53
+ path: dist/
54
+ if-no-files-found: error
55
+
56
+ publish:
57
+ needs: validate
58
+ if: needs.validate.outputs.publish == 'true'
59
+ runs-on: ubuntu-latest
60
+ timeout-minutes: 5
61
+ environment: pypi
62
+ permissions:
63
+ contents: read
64
+ id-token: write
65
+ steps:
66
+ - uses: actions/download-artifact@v4
67
+ with:
68
+ name: distributions
69
+ path: dist/
70
+ - uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,31 @@
1
+ name: Windows process ownership
2
+
3
+ on:
4
+ push:
5
+ paths:
6
+ - src/h2h_dev_tools/process.py
7
+ - tests/test_process*.py
8
+ - pyproject.toml
9
+ - .github/workflows/windows-process.yml
10
+ workflow_dispatch:
11
+
12
+ permissions:
13
+ contents: read
14
+
15
+ jobs:
16
+ windows-process:
17
+ runs-on: windows-latest
18
+ timeout-minutes: 10
19
+ steps:
20
+ - uses: actions/checkout@v4
21
+ - uses: actions/setup-python@v5
22
+ with:
23
+ python-version: "3.14"
24
+ - name: Install project-local test environment
25
+ run: |
26
+ python -m venv .venv
27
+ .venv/Scripts/python -m pip install ".[dev]"
28
+ - name: Verify Windows Job ownership and command execution
29
+ run: >-
30
+ .venv/Scripts/python -B -m pytest -p no:cacheprovider
31
+ tests/test_process.py tests/test_process_integration.py
@@ -0,0 +1,15 @@
1
+ .DS_Store
2
+ .coverage
3
+ .mypy_cache/
4
+ .pytest_cache/
5
+ .ruff_cache/
6
+ .venv
7
+ __pycache__/
8
+ *.egg-info/
9
+ *.py[cod]
10
+ build/
11
+ dist/
12
+ htmlcov/
13
+ node_modules
14
+ package-lock.json
15
+ uv.lock
@@ -0,0 +1,25 @@
1
+ {
2
+ "globs": [
3
+ "**/*.md",
4
+ "!**/.lake/**",
5
+ "!**/.mypy_cache/**",
6
+ "!**/.pytest_cache/**",
7
+ "!**/.ruff_cache/**",
8
+ "!**/.venv/**",
9
+ "!**/*.egg-info/**",
10
+ "!**/build/**",
11
+ "!**/dist/**",
12
+ "!**/node_modules/**"
13
+ ],
14
+ "config": {
15
+ "default": true,
16
+ "MD013": {
17
+ "line_length": 88,
18
+ "code_blocks": false,
19
+ "tables": false
20
+ },
21
+ "MD024": {
22
+ "siblings_only": true
23
+ }
24
+ }
25
+ }
@@ -0,0 +1,98 @@
1
+ {
2
+ "checked_at": "2026-10-11T08:55:45+00:00",
3
+ "manifest_sha256": "9b9b06499ac50d3669becf22ac2223879fe1acabcb92ac7606fa8feebf8eaba2",
4
+ "node": [
5
+ {
6
+ "declared": ">=0.23.2",
7
+ "latest": "0.23.3",
8
+ "latest_satisfies": true,
9
+ "name": "markdownlint-cli2",
10
+ "registry_url": "https://www.npmjs.com/package/markdownlint-cli2"
11
+ }
12
+ ],
13
+ "project_version": "0.2.1",
14
+ "python": [
15
+ {
16
+ "declared": "hatchling>=1.32.0",
17
+ "group": "build",
18
+ "latest": "1.32.4",
19
+ "latest_satisfies": true,
20
+ "name": "hatchling",
21
+ "python_3_14": true,
22
+ "registry_url": "https://pypi.org/project/hatchling/",
23
+ "release_notes": "https://hatch.pypa.io/dev/history/hatchling/",
24
+ "url": "https://pypi.org/project/hatchling/"
25
+ },
26
+ {
27
+ "declared": "packaging>=26.0",
28
+ "group": "runtime",
29
+ "latest": "26.3",
30
+ "latest_satisfies": true,
31
+ "name": "packaging",
32
+ "python_3_14": true,
33
+ "registry_url": "https://pypi.org/project/packaging/",
34
+ "release_notes": null,
35
+ "url": "https://pypi.org/project/packaging/"
36
+ },
37
+ {
38
+ "declared": "build>=1.5.0",
39
+ "group": "optional:dev",
40
+ "latest": "1.6.1",
41
+ "latest_satisfies": true,
42
+ "name": "build",
43
+ "python_3_14": true,
44
+ "registry_url": "https://pypi.org/project/build/",
45
+ "release_notes": "https://build.pypa.io/en/stable/changelog.html",
46
+ "url": "https://pypi.org/project/build/"
47
+ },
48
+ {
49
+ "declared": "hatchling>=1.32.0",
50
+ "group": "optional:dev",
51
+ "latest": "1.32.4",
52
+ "latest_satisfies": true,
53
+ "name": "hatchling",
54
+ "python_3_14": true,
55
+ "registry_url": "https://pypi.org/project/hatchling/",
56
+ "release_notes": "https://hatch.pypa.io/dev/history/hatchling/",
57
+ "url": "https://pypi.org/project/hatchling/"
58
+ },
59
+ {
60
+ "declared": "mypy>=2.3.1",
61
+ "group": "optional:dev",
62
+ "latest": "2.4.0",
63
+ "latest_satisfies": true,
64
+ "name": "mypy",
65
+ "python_3_14": true,
66
+ "registry_url": "https://pypi.org/project/mypy/",
67
+ "release_notes": "https://github.com/python/mypy/blob/master/CHANGELOG.md",
68
+ "url": "https://pypi.org/project/mypy/"
69
+ },
70
+ {
71
+ "declared": "pytest>=9.1.1",
72
+ "group": "optional:dev",
73
+ "latest": "9.1.1",
74
+ "latest_satisfies": true,
75
+ "name": "pytest",
76
+ "python_3_14": true,
77
+ "registry_url": "https://pypi.org/project/pytest/",
78
+ "release_notes": "https://docs.pytest.org/en/stable/changelog.html",
79
+ "url": "https://pypi.org/project/pytest/"
80
+ },
81
+ {
82
+ "declared": "ruff>=0.16.4",
83
+ "group": "optional:dev",
84
+ "latest": "0.17.0",
85
+ "latest_satisfies": true,
86
+ "name": "ruff",
87
+ "python_3_14": true,
88
+ "registry_url": "https://pypi.org/project/ruff/",
89
+ "release_notes": "https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md",
90
+ "url": "https://pypi.org/project/ruff/"
91
+ }
92
+ ],
93
+ "review": {
94
+ "note": "Release 0.2.1 consumer-integration follow-up: registry candidates remain hatchling 1.32.4, packaging 26.3, build 1.6.1, mypy 2.4.0, pytest 9.1.1, Ruff 0.17.0 and markdownlint-cli2 0.23.3, all within existing lower bounds and Python 3.14 support. Reviewed official notes at https://hatch.pypa.io/dev/history/hatchling/ https://build.pypa.io/en/stable/changelog.html https://packaging.pypa.io/en/stable/changelog.html https://mypy.readthedocs.io/en/stable/changelog.html https://docs.pytest.org/en/stable/changelog.html https://github.com/astral-sh/ruff/releases/tag/0.17.0 and https://github.com/DavidAnson/markdownlint-cli2/blob/v0.23.3/CHANGELOG.md during this integration. Explicit py314 and selected Ruff rules, standard strict mypy, Node 26.10.0; no changed bounds or pin exceptions. The prior 0.2.0 full gate passed 262 tests and isolated wheel checks. This follow-up only splits one diagnostic string to satisfy consumer E501, without changing its text or runtime behavior; 6 distribution checks and Ruff/mypy/Markdown passed. Fresh 0.2.1 sdist-derived wheel verified all exported components offline. A new clean environment normally resolved the explicit 0.2.1 candidate plus packaging 26.3; package and metadata origins and all original installed wheel members except rewritten RECORD matched the wheel bytes. All six consumer snapshots regenerated from that installed candidate. Windows native remains unexecuted on macOS.",
95
+ "status": "reviewed"
96
+ },
97
+ "schema": "h2h.dependency-audit.v1"
98
+ }
@@ -0,0 +1,109 @@
1
+ # AGENTS.md
2
+
3
+ ## 政策與溝通
4
+
5
+ - 本檔是本 repository 唯一代理開發政策;可執行細節以 scripts 與設定為準。
6
+ - 最終回覆使用繁體中文;程式碼、命令與 commit message 可使用英文。
7
+ - 不得為了承載回覆新增 Markdown 文件;README 與文件只記錄長期使用契約。
8
+ - 開始實作須說明品質優先,不以最小修改或向後相容限制設計。
9
+ 完成時如實說明具體取捨、介面變化及是否恰好相容。
10
+ - 依 SOLID、KISS、YAGNI、內聚性與低耦合決定抽象邊界。必要局部重構可納入;
11
+ 實質擴大任務、改變未涵蓋公開行為或資料遷移須先取得使用者同意。
12
+ - 直接涉及的 legacy compatibility path 應移除,不保留 shim;不清理無關程式。
13
+
14
+ ## 工具責任
15
+
16
+ - 本專案擁有跨 H2H repository 的開發工具、可安裝 CLI 與可重建工具快照。
17
+ 不擁有 Core schema、runtime facade、adapter 行為或各 consumer 的業務 gate。
18
+ - 共用 Python 實作的唯一手動維護來源是 `src/h2h_dev_tools/`。
19
+ Consumer 的 generated snapshot 必須由 `h2h-dev-tools sync` 產生,禁止手改。
20
+ - Consumer hooks 使用納入自身 Git tree 的 snapshot,離線驗證完整 payload 與
21
+ manifest;不得以任意 sibling checkout 或已安裝的最新版替換 candidate 工具。
22
+ - Snapshot 更新是明確動作,不可在 hooks、一般 pytest 或 merge gate 中下載、
23
+ 安裝、同步或自動修正檔案。產物來源版本及 payload hash 必須可驗證。
24
+ - Consumer 在 `[tool.h2h-dev-tools].components` 明列使用的機制;generator
25
+ 產生完整依賴集合,verifier 必須核對選擇、檔案集合與 bytes。
26
+ Schema-1 只由明確的 `migrate-v1` 一次性轉換工具接納;一般 gate 不保留
27
+ 舊格式 fallback。Shell bootstrap 不得依賴尚未建立的 `.venv`。
28
+ - 工具不得依賴 `h2hdb`、consumer runtime、Pillow 或 FastAPI。
29
+ Consumer 只能在開發流程使用本工具;不得加入 consumer runtime dependencies
30
+ 或由 shipped consumer `src/` import 本工具。
31
+ - 不因外觀相似統一專案特有的 timeout、formal、schema、distribution 或 DB checks。
32
+ 各 repository 的政策與必要驗收仍由該 repository 擁有。
33
+
34
+ ## Git 與整合
35
+
36
+ - 唯讀分析不建立 branch。修改 tracked files 前使用
37
+ `scripts/detect-primary-branch.sh` 判定 primary 並建立專用 task branch。
38
+ 本 repository 預期 primary 為 `master`;有歧義時設定 local
39
+ `workflow.primaryBranch`,不得猜測或連網查詢。
40
+ - 不 stash、reset、clean、覆寫或混入既有使用者修改;dirty checkout 從 committed
41
+ primary 建立獨立 worktree。Task 與 primary 只需 common ancestor。
42
+ - 所有非 merge commit 使用 Conventional Commits;breaking change 使用 `!`
43
+ 或 `BREAKING CHANGE:`。不得使用 `--no-verify`。
44
+ - 任務完成執行 `scripts/git-flow-merge.sh`,以 `--no-ff` 整合;實際 staged
45
+ merge candidate 由 pre-merge hook 檢查版本、文件或完整 gate。
46
+ 失敗須 abort merge 並保留 task branch。成功才安全移除 task worktree 及
47
+ `git branch -d`。合併後 follow-up 使用新 task branch。
48
+ - Primary 禁止 rebase。Hooks 安裝設定 `pull.rebase=false`、primary rebase=false
49
+ 與 `pull.ff=only`。No-op cleanup 只在 task tip 已包含於 primary 時進行。
50
+ - 本機 task branch、commit、merge 及安全清理已獲授權。
51
+ Fetch、pull、push、remote branch、tag、publish、deploy 及 force 操作
52
+ 必須逐次明確授權;既有 PyPI 設定不等於允許發布。
53
+
54
+ ## 版本與依賴
55
+
56
+ - `pyproject.toml` 的 `[project].version` 是唯一版本來源,固定 `X.Y.Z`。
57
+ 1.0 前 `Y` 是 compatibility lane;相容 release 遞增 `Z`,breaking 遞增 `Y`
58
+ 並歸零 `Z`。1.0 後使用 Semantic Versioning。
59
+ - 本專案 shipped 開發工具本身就是 release surface;`src/`、CLI、snapshot
60
+ 格式或構建 metadata 的改變須升版。只有本 repo 自用 tests、scripts、hooks、CI、
61
+ 文件或品質設定的修改不升版。未知路徑須 fail closed 並明確分類。
62
+ - 既有專案的一個 task 只升版一次,以獨立
63
+ `chore(release): bump version to X.Y.Z` commit 提交。
64
+ Breaking/feature 訊號只採計實際修改 release surface 的 commits。
65
+ - 空 repository 的初次 release 明確限定為 `0.1.0`,須從真正 empty baseline
66
+ 建立並驗證 candidate dependency audit;不是一般版本檢查的豁免。
67
+ - 每次 release 執行 `scripts/audit-dependencies.py --review-note "..."`,人工
68
+ 檢查 release notes、Python 相容性及現有 bounds 外最新版,將與版本及完整
69
+ dependency manifest 綁定的 `.release/dependency-audit.json` 納入提交。
70
+ Audit 產生器可連網;commit 與 merge 只能驗證既有 evidence。
71
+ - `requires-python` 使用 `>=3.14`。依賴原則使用 `>=` lower bound,合理 upper
72
+ bound 或排除須有具體相容性理由;不得為求純 stdlib 重寫 PEP 440/508 parser。
73
+ - 單一乾淨 checkout 必須可重建;不得固定依賴 sibling repo。
74
+ 不提交或使用 `uv.lock`、`package-lock.json` 作為重建輸入。
75
+ - Python tools 來自 `.venv`;Markdown tool 來自本 repo `node_modules`。
76
+ Node 安裝使用 `npm install --package-lock=false`。
77
+
78
+ ## 品質與驗收
79
+
80
+ - `pyproject.toml` 是 Ruff 與 strict mypy 唯一設定來源。使用 Ruff formatter,
81
+ 不使用 Black、`mypy.ini` 或系統全域品質工具。
82
+ - `noqa` 與 `type: ignore` 必須指定規則/error code 並有理由。
83
+ 禁止為了通過檢查而全域放寬設定。停用 Ruff 規則須在設定旁說明。
84
+ - `scripts/format.sh` 明確修改檔案;`scripts/check-fast.sh` 只讀、離線且不寫
85
+ Ruff/mypy cache。非文件 commit 執行 fast gate。
86
+ - `scripts/check_change_scope.py` 以 exact Git tree/index 差異選擇 profile。
87
+ Documentation gate 從 candidate 匯出 Markdown,驗 whitespace、README reference
88
+ 及本機 Markdown lint。未知路徑、mode/type 變化與空差異不得降級為文件。
89
+ - `scripts/release-gate.py` 驗證實際 staged two-parent merge candidate,執行版本
90
+ 及適用 profile,檢查前後 candidate 一致;失敗不得產生 merge commit。
91
+ - Full gate 執行 fast、完整離線 pytest、fresh sdist-derived wheel build 及隔離
92
+ installed wheel/CLI smoke。明確手動呼叫 fast/full 不因文件差異而降級。
93
+ - Wheel smoke 僅複製已安裝 `packaging` distribution 供離線 resolver,禁止借用
94
+ editable source 或整個 development site。此結果不代表 registry-backed clean
95
+ dependency resolution;需要該證據時另以明確 wheels/index 執行並分別回報。
96
+ - 新功能涵蓋正常、邊界、錯誤路徑;bug fix 加 regression test。Git 測試使用
97
+ disposable local repositories;不連 production、live account 或外部 network。
98
+ Flaky 視為失敗;skip/xfail 須理由,xfail 預設 strict。
99
+ - GitHub Actions 只保留 trusted publishing 或本機無法驗證的平台檢查,
100
+ 不複製另一套一般 gate。首次發布可明確 dispatch exact version,仍須 default
101
+ branch guard;一般 push 必須是已存在版本的遞增才發布。
102
+
103
+ ## 完成回報
104
+
105
+ 說明品質優先是否遵守及具體取捨;判定不向後相容或品質優先後恰好相容,列明
106
+ 介面/格式影響與移除的 compatibility path。若 breaking,判斷一次性轉換是否
107
+ 可行、是否已提供、用法與限制;不可行時精確說明保留及人工重建範圍。
108
+ 回報版本、impact、dependency audit、commits、檢查及未執行項目、primary 與 merge
109
+ commit、task branch/worktree 清理狀態,以及是否仍未 push、publish、deploy。