engineering-process 1.2.0__tar.gz → 1.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.
- {engineering_process-1.2.0/engineering_process.egg-info → engineering_process-1.2.1}/PKG-INFO +1 -1
- {engineering_process-1.2.0 → engineering_process-1.2.1}/engineering_process/__init__.py +1 -1
- {engineering_process-1.2.0 → engineering_process-1.2.1}/engineering_process/distribution.py +8 -3
- {engineering_process-1.2.0 → engineering_process-1.2.1/engineering_process.egg-info}/PKG-INFO +1 -1
- {engineering_process-1.2.0 → engineering_process-1.2.1}/engineering_process.egg-info/SOURCES.txt +1 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/pyproject.toml +1 -1
- {engineering_process-1.2.0 → engineering_process-1.2.1}/tests/test_automation.py +9 -0
- engineering_process-1.2.1/tests/test_distribution.py +54 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/LICENSE +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/MANIFEST.in +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/README.md +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/engineering_process/__main__.py +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/engineering_process/_supervisor_contract.py +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/engineering_process/_supervisor_posix.py +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/engineering_process/_supervisor_windows.py +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/engineering_process/_windows_job.py +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/engineering_process/adoption.py +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/engineering_process/cli.py +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/engineering_process/commands.py +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/engineering_process/contracts.py +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/engineering_process/helper_launch.py +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/engineering_process/lifecycle.py +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/engineering_process/production_engineering.py +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/engineering_process/project.py +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/engineering_process/publication_compat.py +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/engineering_process/release.py +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/engineering_process/repository.py +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/engineering_process/requirements-dev.txt +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/engineering_process/requirements-runtime.txt +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/engineering_process/skills.py +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/engineering_process/supervision.py +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/engineering_process.egg-info/dependency_links.txt +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/engineering_process.egg-info/entry_points.txt +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/engineering_process.egg-info/requires.txt +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/engineering_process.egg-info/top_level.txt +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/process-graph.json +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/process_assets/skills/finish-change/SKILL.md +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/process_assets/skills/implement-change/SKILL.md +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/process_assets/skills/improve-process/SKILL.md +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/process_assets/skills/plan-change/SKILL.md +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/process_assets/skills/production-engineering/SKILL.md +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/process_assets/skills/production-engineering/invariants.json +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/process_assets/skills/review-change/SKILL.md +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/process_assets/skills/run-change/SKILL.md +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/process_assets/skills/start-change/SKILL.md +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/process_assets/skills/verify-change/SKILL.md +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/schemas/change.schema.json +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/schemas/plan.schema.json +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/schemas/process-graph.schema.json +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/schemas/process-lock.schema.json +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/schemas/production-engineering.schema.json +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/schemas/project-legacy.schema.json +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/schemas/project.schema.json +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/schemas/receipt.schema.json +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/schemas/release-change.schema.json +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/schemas/release.schema.json +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/schemas/review.schema.json +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/schemas/run.schema.json +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/setup.cfg +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/templates/AGENTS.process.md +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/templates/PULL_REQUEST_TEMPLATE.md +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/templates/adopt-process-windows-job.py +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/templates/adopt-process.py +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/tests/test_adoption.py +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/tests/test_architecture.py +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/tests/test_cli.py +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/tests/test_commands.py +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/tests/test_contracts.py +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/tests/test_lifecycle.py +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/tests/test_production_engineering.py +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/tests/test_publication_compat.py +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/tests/test_release.py +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/tests/test_repository.py +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/tests/test_skills.py +0 -0
- {engineering_process-1.2.0 → engineering_process-1.2.1}/tests/test_supervisor_posix.py +0 -0
|
@@ -65,12 +65,17 @@ def skill_names(root: Path) -> tuple[str, ...]:
|
|
|
65
65
|
return names
|
|
66
66
|
|
|
67
67
|
|
|
68
|
+
def _ordered_paths(root: Path, paths: Iterable[Path]) -> list[Path]:
|
|
69
|
+
return sorted(paths, key=lambda path: path.relative_to(root).as_posix())
|
|
70
|
+
|
|
71
|
+
|
|
68
72
|
def _asset_paths(root: Path) -> Iterable[tuple[str, Path]]:
|
|
69
73
|
skill_directory = skills_root(root)
|
|
70
|
-
for path in
|
|
74
|
+
for path in _ordered_paths(skill_directory, skill_directory.rglob("*")):
|
|
71
75
|
if path.is_file():
|
|
72
76
|
yield f"skills/{path.relative_to(skill_directory).as_posix()}", path
|
|
73
|
-
|
|
77
|
+
schema_directory = schemas_root(root)
|
|
78
|
+
for path in _ordered_paths(schema_directory, schema_directory.glob("*.json")):
|
|
74
79
|
yield f"schemas/{path.name}", path
|
|
75
80
|
for name in (
|
|
76
81
|
"AGENTS.process.md",
|
|
@@ -110,7 +115,7 @@ def distribution_digest(root: Path) -> str:
|
|
|
110
115
|
|
|
111
116
|
def skill_digest(path: Path) -> str:
|
|
112
117
|
digest = hashlib.sha256()
|
|
113
|
-
for file_path in
|
|
118
|
+
for file_path in _ordered_paths(path, path.rglob("*")):
|
|
114
119
|
if not file_path.is_file() or file_path.name == ".engineering-process.json":
|
|
115
120
|
continue
|
|
116
121
|
relative = file_path.relative_to(path).as_posix().encode("utf-8")
|
|
@@ -104,6 +104,15 @@ class AutomationTests(unittest.TestCase):
|
|
|
104
104
|
)
|
|
105
105
|
self.assertIn("needs: [metadata, publish]", workflow)
|
|
106
106
|
self.assertIn("Verify PyPI exposes the exact built hashes", workflow)
|
|
107
|
+
visibility = workflow.split(
|
|
108
|
+
" - name: Verify PyPI exposes the exact built hashes\n", maxsplit=1
|
|
109
|
+
)[1].split(" - name: Create short-lived release token\n", maxsplit=1)[0]
|
|
110
|
+
self.assertIn("for attempt in range(12)", visibility)
|
|
111
|
+
self.assertIn('"Accept": "application/vnd.pypi.simple.v1+json"', visibility)
|
|
112
|
+
self.assertIn(
|
|
113
|
+
"if actual == expected and simple_actual == expected:", visibility
|
|
114
|
+
)
|
|
115
|
+
self.assertIn("PyPI Simple API did not return PEP 691 JSON", visibility)
|
|
107
116
|
self.assertIn("SOURCE_DATE_EPOCH", workflow)
|
|
108
117
|
self.assertIn("verification/normalize_sdist.py", workflow)
|
|
109
118
|
self.assertIn("points to a different commit", workflow)
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import hashlib
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
import tempfile
|
|
6
|
+
import unittest
|
|
7
|
+
|
|
8
|
+
from engineering_process.distribution import distribution_digest, skill_digest
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def framed_digest(entries: list[tuple[str, bytes]]) -> str:
|
|
12
|
+
digest = hashlib.sha256()
|
|
13
|
+
for relative, data in entries:
|
|
14
|
+
encoded = relative.encode("utf-8")
|
|
15
|
+
digest.update(len(encoded).to_bytes(4, "big"))
|
|
16
|
+
digest.update(encoded)
|
|
17
|
+
digest.update(len(data).to_bytes(8, "big"))
|
|
18
|
+
digest.update(data)
|
|
19
|
+
return "sha256:" + digest.hexdigest()
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class DistributionTests(unittest.TestCase):
|
|
23
|
+
def test_digests_follow_canonical_relative_posix_order(self) -> None:
|
|
24
|
+
entries = [
|
|
25
|
+
("skills/sample/SKILL.md", b"skill\n"),
|
|
26
|
+
("skills/sample/invariants.json", b"{}\n"),
|
|
27
|
+
("schemas/sample.json", b"{}\n"),
|
|
28
|
+
("templates/AGENTS.process.md", b"agents\n"),
|
|
29
|
+
("templates/PULL_REQUEST_TEMPLATE.md", b"pull request\n"),
|
|
30
|
+
("templates/adopt-process.py", b"adopt\n"),
|
|
31
|
+
("templates/adopt-process-windows-job.py", b"windows\n"),
|
|
32
|
+
("process-graph.json", b"{}\n"),
|
|
33
|
+
]
|
|
34
|
+
with tempfile.TemporaryDirectory() as directory:
|
|
35
|
+
root = Path(directory)
|
|
36
|
+
for relative, data in entries:
|
|
37
|
+
path = root / relative.replace("skills/", "process_assets/skills/", 1)
|
|
38
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
39
|
+
path.write_bytes(data)
|
|
40
|
+
|
|
41
|
+
self.assertEqual(framed_digest(entries), distribution_digest(root))
|
|
42
|
+
self.assertEqual(
|
|
43
|
+
framed_digest(
|
|
44
|
+
[
|
|
45
|
+
("SKILL.md", b"skill\n"),
|
|
46
|
+
("invariants.json", b"{}\n"),
|
|
47
|
+
]
|
|
48
|
+
),
|
|
49
|
+
skill_digest(root / "process_assets" / "skills" / "sample"),
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
if __name__ == "__main__":
|
|
54
|
+
unittest.main()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{engineering_process-1.2.0 → engineering_process-1.2.1}/engineering_process/_supervisor_contract.py
RENAMED
|
File without changes
|
{engineering_process-1.2.0 → engineering_process-1.2.1}/engineering_process/_supervisor_posix.py
RENAMED
|
File without changes
|
{engineering_process-1.2.0 → engineering_process-1.2.1}/engineering_process/_supervisor_windows.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{engineering_process-1.2.0 → engineering_process-1.2.1}/engineering_process/helper_launch.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{engineering_process-1.2.0 → engineering_process-1.2.1}/engineering_process/publication_compat.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{engineering_process-1.2.0 → engineering_process-1.2.1}/engineering_process/requirements-dev.txt
RENAMED
|
File without changes
|
{engineering_process-1.2.0 → engineering_process-1.2.1}/engineering_process/requirements-runtime.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{engineering_process-1.2.0 → engineering_process-1.2.1}/engineering_process.egg-info/requires.txt
RENAMED
|
File without changes
|
{engineering_process-1.2.0 → engineering_process-1.2.1}/engineering_process.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
{engineering_process-1.2.0 → engineering_process-1.2.1}/process_assets/skills/finish-change/SKILL.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{engineering_process-1.2.0 → engineering_process-1.2.1}/process_assets/skills/plan-change/SKILL.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{engineering_process-1.2.0 → engineering_process-1.2.1}/process_assets/skills/review-change/SKILL.md
RENAMED
|
File without changes
|
{engineering_process-1.2.0 → engineering_process-1.2.1}/process_assets/skills/run-change/SKILL.md
RENAMED
|
File without changes
|
{engineering_process-1.2.0 → engineering_process-1.2.1}/process_assets/skills/start-change/SKILL.md
RENAMED
|
File without changes
|
{engineering_process-1.2.0 → engineering_process-1.2.1}/process_assets/skills/verify-change/SKILL.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{engineering_process-1.2.0 → engineering_process-1.2.1}/schemas/production-engineering.schema.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{engineering_process-1.2.0 → engineering_process-1.2.1}/templates/adopt-process-windows-job.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{engineering_process-1.2.0 → engineering_process-1.2.1}/tests/test_production_engineering.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|