worktrust 0.10.13__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 (34) hide show
  1. worktrust-0.10.13/LICENSE +21 -0
  2. worktrust-0.10.13/MANIFEST.in +4 -0
  3. worktrust-0.10.13/PKG-INFO +110 -0
  4. worktrust-0.10.13/README.md +98 -0
  5. worktrust-0.10.13/VERSION +1 -0
  6. worktrust-0.10.13/build_runtime.py +115 -0
  7. worktrust-0.10.13/pyproject.toml +29 -0
  8. worktrust-0.10.13/runtime-lock.json +36 -0
  9. worktrust-0.10.13/setup.cfg +4 -0
  10. worktrust-0.10.13/setup.py +55 -0
  11. worktrust-0.10.13/src/worktrust.egg-info/PKG-INFO +110 -0
  12. worktrust-0.10.13/src/worktrust.egg-info/SOURCES.txt +32 -0
  13. worktrust-0.10.13/src/worktrust.egg-info/dependency_links.txt +1 -0
  14. worktrust-0.10.13/src/worktrust.egg-info/entry_points.txt +2 -0
  15. worktrust-0.10.13/src/worktrust.egg-info/top_level.txt +1 -0
  16. worktrust-0.10.13/src/worktrust_cli/__init__.py +88 -0
  17. worktrust-0.10.13/src/worktrust_cli/__main__.py +4 -0
  18. worktrust-0.10.13/src/worktrust_cli/bundle/chat-exports.mjs +240 -0
  19. worktrust-0.10.13/src/worktrust_cli/bundle/config-edits.mjs +87 -0
  20. worktrust-0.10.13/src/worktrust_cli/bundle/count-behaviour.mjs +1393 -0
  21. worktrust-0.10.13/src/worktrust_cli/bundle/log-session.mjs +1330 -0
  22. worktrust-0.10.13/src/worktrust_cli/bundle/manifest.json +19 -0
  23. worktrust-0.10.13/src/worktrust_cli/bundle/preserve-lines.mjs +252 -0
  24. worktrust-0.10.13/src/worktrust_cli/bundle/preserve-summary.mjs +42 -0
  25. worktrust-0.10.13/src/worktrust_cli/bundle/preserve.mjs +390 -0
  26. worktrust-0.10.13/src/worktrust_cli/bundle/runtime-install.mjs +64 -0
  27. worktrust-0.10.13/src/worktrust_cli/bundle/session-databases.mjs +472 -0
  28. worktrust-0.10.13/src/worktrust_cli/bundle/setup-mcp.mjs +343 -0
  29. worktrust-0.10.13/src/worktrust_cli/bundle/stack-rules.mjs +153 -0
  30. worktrust-0.10.13/src/worktrust_cli/bundle/stretch-evidence.mjs +748 -0
  31. worktrust-0.10.13/src/worktrust_cli/bundle/transcript-readers.mjs +269 -0
  32. worktrust-0.10.13/src/worktrust_cli/bundle/worktrust.mjs +1196 -0
  33. worktrust-0.10.13/tests/test_distribution.py +189 -0
  34. worktrust-0.10.13/tests/test_runtime_build.py +87 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 WorkTrust
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.
@@ -0,0 +1,4 @@
1
+ include VERSION LICENSE README.md runtime-lock.json build_runtime.py setup.py
2
+ recursive-include src/worktrust_cli/bundle *.mjs *.json
3
+ recursive-include tests *.py
4
+ prune src/worktrust_cli/runtime
@@ -0,0 +1,110 @@
1
+ Metadata-Version: 2.4
2
+ Name: worktrust
3
+ Version: 0.10.13
4
+ Summary: The WorkTrust CLI, using the same measurement engine as npm
5
+ License-Expression: MIT
6
+ Project-URL: Homepage, https://worktrust.io
7
+ Project-URL: Source, https://github.com/fhomey/worktrust-cli
8
+ Requires-Python: >=3.10
9
+ Description-Content-Type: text/markdown
10
+ License-File: LICENSE
11
+ Dynamic: license-file
12
+
13
+ # WorkTrust for Python tool runners
14
+
15
+ This package launches the same JavaScript measurement engine shipped in the WorkTrust npm
16
+ package. It does not implement another measurement engine or a Python instrumentation SDK.
17
+ Python 3.10+ is required. Supported platform wheels include **Node.js 22.23.3**; no separate
18
+ Node or npm installation is needed. The launcher uses that bundled runtime, never downloads a
19
+ runtime when invoked, and does not silently switch to another CLI version.
20
+
21
+ Wheels target macOS 11+ (Intel and Apple Silicon), Linux with glibc 2.28+ (x64 and arm64), and
22
+ Windows 10+ (x64 and arm64). Linux also requires the Node-supported system C++ runtime
23
+ (GLIBCXX_3.4.25 or newer). Alpine/musl, 32-bit systems and other platforms are not supported.
24
+ A source distribution cannot fetch Node automatically: a source build requires the explicit
25
+ maintainer preparation step below. Supported users should install the matching wheel.
26
+
27
+ After publication under a verified WorkTrust-owned PyPI project, the intended commands are:
28
+
29
+ ```sh
30
+ uvx worktrust preserve
31
+ pipx run worktrust preserve
32
+ ```
33
+
34
+ These public commands are not a claim that this package has already been published. Test a
35
+ reviewed local wheel first:
36
+
37
+ ```sh
38
+ uvx --from /absolute/path/worktrust-VERSION-py3-none-PLATFORM.whl worktrust --help
39
+ pipx run --spec /absolute/path/worktrust-VERSION-py3-none-PLATFORM.whl worktrust --help
40
+ ```
41
+
42
+ Use your package manager to choose and update the installed version. The package contains
43
+ the CLI modules and Node runtime, so `preserve` itself needs no network after installation. It reads supported
44
+ local session files and can change retention settings or create local metadata archives;
45
+ only the person runs it. Existing WorkTrust agent safeguards and consent prompts remain.
46
+ Other commands can contact WorkTrust. Package installation itself can contact registries.
47
+
48
+ After PyPI publication, explicitly request the latest published package when needed:
49
+
50
+ ```sh
51
+ uvx worktrust@latest preserve
52
+ pipx run --no-cache worktrust preserve
53
+ ```
54
+
55
+ For persistent installations, use `uv tool upgrade worktrust` or `pipx upgrade worktrust`.
56
+ An existing cache or version constraint can otherwise keep an older release. `worktrust update`
57
+ refreshes the computer coupling using the selected package; it does not upgrade the Python package.
58
+
59
+ Runtime bundle hashes detect missing or changed files; they are not hardware attestation or
60
+ independent proof of authenticity. Request and archive signatures retain the existing CLI's
61
+ software-key threat model. See the npm package SECURITY.md and README.md for the data contract.
62
+
63
+ ## Maintainers
64
+
65
+ Running `node tools/worktrust-cli/sync.mjs` from the monorepo also regenerates the Python JavaScript
66
+ bundle and version. `node scripts/build-python-cli.mjs --check` refuses drift. The native runtime
67
+ is a separate build artifact, excluded from Git and sdists. Explicitly prepare it before building:
68
+
69
+ ```sh
70
+ python tools/worktrust-python/build_runtime.py
71
+ python -m build --wheel tools/worktrust-python
72
+ python -m build --sdist tools/worktrust-python
73
+ ```
74
+
75
+ `build_runtime.py` downloads one official Node archive from nodejs.org at build time, verifies its
76
+ committed SHA256 from `runtime-lock.json`, and extracts only the executable and complete LICENSE.
77
+ It accepts `--target` for a reviewed target and `--cache` for a build cache. Platform wheel tags
78
+ follow the selected runtime. Never label these wheels `any`. Building a wheel from the sdist
79
+ fails closed until this explicit preparation step has been performed; no install hook downloads code.
80
+
81
+ Run `python tools/worktrust-python/tests/test_runtime_build.py`, then
82
+ `node scripts/test-python-cli.mjs` with a Python containing the build requirements (select it with
83
+ `WORKTRUST_TEST_PYTHON`). Tests build and exercise a real wheel using its own runtime with no Node
84
+ on PATH; they use synthetic homes and metadata only. Native execution must pass independently on
85
+ all six claimed OS/architecture combinations before release. Cross-building alone is not that proof.
86
+ Set `WORKTRUST_REQUIRE_TOOL_RUNNERS=1` to require actual uv and pipx wheel smoke tests, and
87
+ `WORKTRUST_TEST_ARTIFACT_DIR` to a fresh directory to retain the exact tested wheel and sdist.
88
+ Existing artifacts are never overwritten. Canonical module bytes match across channels;
89
+ bit-for-bit reproducibility of whole wheel or sdist archives is not asserted.
90
+
91
+ The public `fhomey/worktrust-cli` repository carries this package under `python/`, alongside the
92
+ npm package at its root. There, install `python/requirements-release.txt`, run
93
+ `python python/build_runtime.py`, then `python python/tests/test_distribution.py` with
94
+ `WORKTRUST_TEST_CLI_SOURCE` set to the repository's absolute path and
95
+ `WORKTRUST_REQUIRE_TOOL_RUNNERS=1`. The test derives Node from the built wheel; it does not require
96
+ a system Node installation. Keep build-only workflow results distinct from successful publication.
97
+
98
+ The inactive `release-pypi.yml.example` targets this public layout. Its intended active filename
99
+ is `.github/workflows/release-pypi.yml`, using the protected `pypi` environment and PyPI Trusted
100
+ Publishing. Once activated, the same GitHub release triggers both registries; manual execution
101
+ supports the initial Python publication and retries. npm also requires the supported-platform Python
102
+ artifact/parity tests before publishing. Both channels use the same version and module bytes.
103
+ Approvals and registry failures remain separate; confirm both publications before announcing a
104
+ release as available on both channels. Neither workflow invokes a Vercel deployment.
105
+
106
+ Do not edit generated `bundle/`, `VERSION` or `LICENSE`. Publication requires confirmed
107
+ PyPI ownership and a configured Trusted Publisher; source readiness does not grant that.
108
+
109
+ Official runtime platform requirements: https://github.com/nodejs/node/blob/v22.23.3/BUILDING.md
110
+ Pinned upstream archive checksums: https://nodejs.org/dist/v22.23.3/SHASUMS256.txt
@@ -0,0 +1,98 @@
1
+ # WorkTrust for Python tool runners
2
+
3
+ This package launches the same JavaScript measurement engine shipped in the WorkTrust npm
4
+ package. It does not implement another measurement engine or a Python instrumentation SDK.
5
+ Python 3.10+ is required. Supported platform wheels include **Node.js 22.23.3**; no separate
6
+ Node or npm installation is needed. The launcher uses that bundled runtime, never downloads a
7
+ runtime when invoked, and does not silently switch to another CLI version.
8
+
9
+ Wheels target macOS 11+ (Intel and Apple Silicon), Linux with glibc 2.28+ (x64 and arm64), and
10
+ Windows 10+ (x64 and arm64). Linux also requires the Node-supported system C++ runtime
11
+ (GLIBCXX_3.4.25 or newer). Alpine/musl, 32-bit systems and other platforms are not supported.
12
+ A source distribution cannot fetch Node automatically: a source build requires the explicit
13
+ maintainer preparation step below. Supported users should install the matching wheel.
14
+
15
+ After publication under a verified WorkTrust-owned PyPI project, the intended commands are:
16
+
17
+ ```sh
18
+ uvx worktrust preserve
19
+ pipx run worktrust preserve
20
+ ```
21
+
22
+ These public commands are not a claim that this package has already been published. Test a
23
+ reviewed local wheel first:
24
+
25
+ ```sh
26
+ uvx --from /absolute/path/worktrust-VERSION-py3-none-PLATFORM.whl worktrust --help
27
+ pipx run --spec /absolute/path/worktrust-VERSION-py3-none-PLATFORM.whl worktrust --help
28
+ ```
29
+
30
+ Use your package manager to choose and update the installed version. The package contains
31
+ the CLI modules and Node runtime, so `preserve` itself needs no network after installation. It reads supported
32
+ local session files and can change retention settings or create local metadata archives;
33
+ only the person runs it. Existing WorkTrust agent safeguards and consent prompts remain.
34
+ Other commands can contact WorkTrust. Package installation itself can contact registries.
35
+
36
+ After PyPI publication, explicitly request the latest published package when needed:
37
+
38
+ ```sh
39
+ uvx worktrust@latest preserve
40
+ pipx run --no-cache worktrust preserve
41
+ ```
42
+
43
+ For persistent installations, use `uv tool upgrade worktrust` or `pipx upgrade worktrust`.
44
+ An existing cache or version constraint can otherwise keep an older release. `worktrust update`
45
+ refreshes the computer coupling using the selected package; it does not upgrade the Python package.
46
+
47
+ Runtime bundle hashes detect missing or changed files; they are not hardware attestation or
48
+ independent proof of authenticity. Request and archive signatures retain the existing CLI's
49
+ software-key threat model. See the npm package SECURITY.md and README.md for the data contract.
50
+
51
+ ## Maintainers
52
+
53
+ Running `node tools/worktrust-cli/sync.mjs` from the monorepo also regenerates the Python JavaScript
54
+ bundle and version. `node scripts/build-python-cli.mjs --check` refuses drift. The native runtime
55
+ is a separate build artifact, excluded from Git and sdists. Explicitly prepare it before building:
56
+
57
+ ```sh
58
+ python tools/worktrust-python/build_runtime.py
59
+ python -m build --wheel tools/worktrust-python
60
+ python -m build --sdist tools/worktrust-python
61
+ ```
62
+
63
+ `build_runtime.py` downloads one official Node archive from nodejs.org at build time, verifies its
64
+ committed SHA256 from `runtime-lock.json`, and extracts only the executable and complete LICENSE.
65
+ It accepts `--target` for a reviewed target and `--cache` for a build cache. Platform wheel tags
66
+ follow the selected runtime. Never label these wheels `any`. Building a wheel from the sdist
67
+ fails closed until this explicit preparation step has been performed; no install hook downloads code.
68
+
69
+ Run `python tools/worktrust-python/tests/test_runtime_build.py`, then
70
+ `node scripts/test-python-cli.mjs` with a Python containing the build requirements (select it with
71
+ `WORKTRUST_TEST_PYTHON`). Tests build and exercise a real wheel using its own runtime with no Node
72
+ on PATH; they use synthetic homes and metadata only. Native execution must pass independently on
73
+ all six claimed OS/architecture combinations before release. Cross-building alone is not that proof.
74
+ Set `WORKTRUST_REQUIRE_TOOL_RUNNERS=1` to require actual uv and pipx wheel smoke tests, and
75
+ `WORKTRUST_TEST_ARTIFACT_DIR` to a fresh directory to retain the exact tested wheel and sdist.
76
+ Existing artifacts are never overwritten. Canonical module bytes match across channels;
77
+ bit-for-bit reproducibility of whole wheel or sdist archives is not asserted.
78
+
79
+ The public `fhomey/worktrust-cli` repository carries this package under `python/`, alongside the
80
+ npm package at its root. There, install `python/requirements-release.txt`, run
81
+ `python python/build_runtime.py`, then `python python/tests/test_distribution.py` with
82
+ `WORKTRUST_TEST_CLI_SOURCE` set to the repository's absolute path and
83
+ `WORKTRUST_REQUIRE_TOOL_RUNNERS=1`. The test derives Node from the built wheel; it does not require
84
+ a system Node installation. Keep build-only workflow results distinct from successful publication.
85
+
86
+ The inactive `release-pypi.yml.example` targets this public layout. Its intended active filename
87
+ is `.github/workflows/release-pypi.yml`, using the protected `pypi` environment and PyPI Trusted
88
+ Publishing. Once activated, the same GitHub release triggers both registries; manual execution
89
+ supports the initial Python publication and retries. npm also requires the supported-platform Python
90
+ artifact/parity tests before publishing. Both channels use the same version and module bytes.
91
+ Approvals and registry failures remain separate; confirm both publications before announcing a
92
+ release as available on both channels. Neither workflow invokes a Vercel deployment.
93
+
94
+ Do not edit generated `bundle/`, `VERSION` or `LICENSE`. Publication requires confirmed
95
+ PyPI ownership and a configured Trusted Publisher; source readiness does not grant that.
96
+
97
+ Official runtime platform requirements: https://github.com/nodejs/node/blob/v22.23.3/BUILDING.md
98
+ Pinned upstream archive checksums: https://nodejs.org/dist/v22.23.3/SHASUMS256.txt
@@ -0,0 +1 @@
1
+ 0.10.13
@@ -0,0 +1,115 @@
1
+ """Explicit build-time fetch of pinned official Node binaries. Never imported by the CLI."""
2
+ import argparse
3
+ import hashlib
4
+ import io
5
+ import json
6
+ from pathlib import Path
7
+ import platform
8
+ import shutil
9
+ import stat
10
+ import tarfile
11
+ import tempfile
12
+ import urllib.request
13
+ import zipfile
14
+
15
+ ROOT = Path(__file__).resolve().parent
16
+ MAX_ARCHIVE = 150 * 1024 * 1024
17
+ MAX_BINARY = 200 * 1024 * 1024
18
+
19
+
20
+ def host_target():
21
+ system = {"Darwin":"darwin", "Linux":"linux", "Windows":"win"}.get(platform.system())
22
+ architecture = {"x86_64":"x64", "amd64":"x64", "arm64":"arm64", "aarch64":"arm64"}.get(platform.machine().lower())
23
+ target = f"{system}-{architecture}"
24
+ if system is None or architecture is None:
25
+ raise ValueError(f"unsupported runtime platform: {target}")
26
+ return target
27
+
28
+
29
+ def selected_members(data, archive_name, executable):
30
+ """Copy only two exact regular members; never extract archive paths or links."""
31
+ suffix = ".zip" if archive_name.endswith(".zip") else ".tar.gz" if archive_name.endswith(".tar.gz") else ".tar.xz"
32
+ prefix = archive_name[:-len(suffix)]
33
+ expected = {f"{prefix}/{'node.exe' if executable == 'node.exe' else 'bin/node'}":executable,
34
+ f"{prefix}/LICENSE":"LICENSE"}
35
+ result = {}
36
+ if suffix == ".zip":
37
+ with zipfile.ZipFile(io.BytesIO(data)) as archive:
38
+ for member in archive.infolist():
39
+ if member.filename not in expected:
40
+ continue
41
+ mode = member.external_attr >> 16
42
+ if member.is_dir() or stat.S_ISLNK(mode) or (stat.S_IFMT(mode) not in (0, stat.S_IFREG)):
43
+ raise ValueError("runtime archive member must be a regular file")
44
+ if member.file_size > MAX_BINARY or member.filename in result:
45
+ raise ValueError("invalid runtime archive member")
46
+ result[member.filename] = archive.read(member)
47
+ else:
48
+ with tarfile.open(fileobj=io.BytesIO(data), mode="r:*") as archive:
49
+ for member in archive:
50
+ if member.name not in expected:
51
+ continue
52
+ if not member.isfile() or member.size > MAX_BINARY or member.name in result:
53
+ raise ValueError("invalid runtime archive member")
54
+ stream = archive.extractfile(member)
55
+ result[member.name] = stream.read(MAX_BINARY + 1)
56
+ if set(result) != set(expected):
57
+ raise ValueError("runtime archive is missing an expected file")
58
+ if any(not value or len(value) > MAX_BINARY for value in result.values()):
59
+ raise ValueError("runtime archive member size invalid")
60
+ return {expected[name]: value for name, value in result.items()}
61
+
62
+
63
+ def prepare(target, cache):
64
+ lock = json.loads((ROOT / "runtime-lock.json").read_text())
65
+ item = lock["targets"].get(target)
66
+ if item is None:
67
+ raise ValueError(f"unsupported runtime target: {target}")
68
+ cache.mkdir(parents=True, exist_ok=True)
69
+ cached = cache / item["archive"]
70
+ if cached.is_symlink():
71
+ raise ValueError("runtime archive cache must not be a symlink")
72
+ if cached.exists():
73
+ if cached.stat().st_size > MAX_ARCHIVE:
74
+ raise ValueError("runtime archive too large")
75
+ data = cached.read_bytes()
76
+ else:
77
+ request = urllib.request.Request(lock["base_url"] + item["archive"], headers={"User-Agent":"WorkTrust-runtime-build"})
78
+ with urllib.request.urlopen(request, timeout=60) as response:
79
+ if not response.url.startswith("https://nodejs.org/dist/"):
80
+ raise ValueError("runtime download redirected away from official origin")
81
+ data = response.read(MAX_ARCHIVE + 1)
82
+ if len(data) > MAX_ARCHIVE or hashlib.sha256(data).hexdigest() != item["sha256"]:
83
+ raise ValueError("official runtime archive checksum mismatch")
84
+ if not cached.exists():
85
+ with tempfile.NamedTemporaryFile(dir=cache, delete=False) as handle:
86
+ handle.write(data)
87
+ pending = Path(handle.name)
88
+ pending.replace(cached)
89
+ executable = "node.exe" if target.startswith("win-") else "node"
90
+ members = selected_members(data, item["archive"], executable)
91
+ destination = ROOT / "src/worktrust_cli/runtime"
92
+ if destination.is_symlink():
93
+ raise ValueError("runtime staging directory must not be a symlink")
94
+ destination.mkdir(parents=True, exist_ok=True)
95
+ for entry in destination.iterdir():
96
+ if entry.is_dir() and not entry.is_symlink():
97
+ raise ValueError("unexpected directory in runtime stage")
98
+ entry.unlink()
99
+ for name, payload in members.items():
100
+ path = destination/name
101
+ path.write_bytes(payload)
102
+ path.chmod(0o755 if name == executable else 0o644)
103
+ descriptor = {"version":lock["version"], "platform":target, "executable":executable,
104
+ "archive_sha256":item["sha256"],
105
+ "files":{name:hashlib.sha256(payload).hexdigest() for name,payload in sorted(members.items())}}
106
+ (destination/"runtime.json").write_text(json.dumps(descriptor,indent=2)+"\n")
107
+ print(f"Staged Node {lock['version']} for {target}; official archive SHA256 verified")
108
+
109
+
110
+ if __name__ == "__main__":
111
+ parser = argparse.ArgumentParser(description=__doc__)
112
+ parser.add_argument("--target", default=host_target())
113
+ parser.add_argument("--cache", type=Path, default=Path(tempfile.gettempdir())/"worktrust-node-build-cache")
114
+ args = parser.parse_args()
115
+ prepare(args.target, args.cache)
@@ -0,0 +1,29 @@
1
+ [build-system]
2
+ requires = ["setuptools>=77"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "worktrust"
7
+ dynamic = ["version"]
8
+ description = "The WorkTrust CLI, using the same measurement engine as npm"
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ license = "MIT"
12
+ license-files = ["LICENSE"]
13
+ dependencies = []
14
+
15
+ [project.scripts]
16
+ worktrust = "worktrust_cli:main"
17
+
18
+ [project.urls]
19
+ Homepage = "https://worktrust.io"
20
+ Source = "https://github.com/fhomey/worktrust-cli"
21
+
22
+ [tool.setuptools.dynamic]
23
+ version = {file = "VERSION"}
24
+
25
+ [tool.setuptools.packages.find]
26
+ where = ["src"]
27
+
28
+ [tool.setuptools.package-data]
29
+ worktrust_cli = ["bundle/*.mjs", "bundle/manifest.json", "runtime/*"]
@@ -0,0 +1,36 @@
1
+ {
2
+ "version": "22.23.3",
3
+ "base_url": "https://nodejs.org/dist/v22.23.3/",
4
+ "targets": {
5
+ "darwin-arm64": {
6
+ "archive": "node-v22.23.3-darwin-arm64.tar.gz",
7
+ "sha256": "23b25245dcfb9af7262f8ff142e9e2e0af025368117329e7a7458a51e5922f53",
8
+ "wheel_tag": "macosx_11_0_arm64"
9
+ },
10
+ "darwin-x64": {
11
+ "archive": "node-v22.23.3-darwin-x64.tar.gz",
12
+ "sha256": "8a677b0219178efd6eb0e475457c4afb452b521a92f6e67845a73bd85727f2a8",
13
+ "wheel_tag": "macosx_11_0_x86_64"
14
+ },
15
+ "linux-arm64": {
16
+ "archive": "node-v22.23.3-linux-arm64.tar.xz",
17
+ "sha256": "a44aeb94849a299b22df10b9e622ec2f605c2183501bc40590705131de7c740f",
18
+ "wheel_tag": "manylinux_2_28_aarch64"
19
+ },
20
+ "linux-x64": {
21
+ "archive": "node-v22.23.3-linux-x64.tar.xz",
22
+ "sha256": "df450af89261115ef9f9e3830c3eeb2cc9213b63c720b1af623cb5dcbe2e02de",
23
+ "wheel_tag": "manylinux_2_28_x86_64"
24
+ },
25
+ "win-arm64": {
26
+ "archive": "node-v22.23.3-win-arm64.zip",
27
+ "sha256": "33dad22e4cef5ee8f9fbb1b0d037fdacd0e56d12a4580f0d63f68b894deab535",
28
+ "wheel_tag": "win_arm64"
29
+ },
30
+ "win-x64": {
31
+ "archive": "node-v22.23.3-win-x64.zip",
32
+ "sha256": "2b0ff57b049cda1bbcea2240eec20467018713c1efe1f7360c2681859b90ed71",
33
+ "wheel_tag": "win_amd64"
34
+ }
35
+ }
36
+ }
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,55 @@
1
+ """Platform wheels carrying Node; Python code itself has no interpreter-specific ABI."""
2
+ import hashlib
3
+ import json
4
+ from pathlib import Path
5
+ from setuptools import setup
6
+ from setuptools.dist import Distribution
7
+ from setuptools.command.build_py import build_py
8
+ from setuptools.command.bdist_wheel import bdist_wheel
9
+
10
+ ROOT = Path(__file__).resolve().parent
11
+
12
+
13
+ def runtime():
14
+ directory = ROOT/"src/worktrust_cli/runtime"
15
+ descriptor = directory/"runtime.json"
16
+ if not descriptor.is_file() or descriptor.is_symlink():
17
+ raise RuntimeError("Bundled runtime is absent. Run python build_runtime.py explicitly before building a wheel; runtime downloads never occur during installation or CLI execution.")
18
+ data = json.loads(descriptor.read_text())
19
+ lock = json.loads((ROOT/"runtime-lock.json").read_text())
20
+ expected = lock["targets"].get(data["platform"])
21
+ if expected is None or data["version"] != lock["version"] or data["archive_sha256"] != expected["sha256"]:
22
+ raise RuntimeError("Staged runtime does not match the reviewed runtime lock")
23
+ executable = "node.exe" if data["platform"].startswith("win-") else "node"
24
+ if data["executable"] != executable or set(data["files"]) != {executable,"LICENSE"}:
25
+ raise RuntimeError("Staged runtime has an invalid file list")
26
+ if {path.name for path in directory.iterdir()} != {executable,"LICENSE","runtime.json"}:
27
+ raise RuntimeError("Unexpected runtime file")
28
+ for name,digest in data["files"].items():
29
+ path = directory/name
30
+ if path.is_symlink() or hashlib.sha256(path.read_bytes()).hexdigest() != digest:
31
+ raise RuntimeError("Staged runtime integrity mismatch")
32
+ return expected["wheel_tag"]
33
+
34
+
35
+ class BuildPython(build_py):
36
+ def run(self):
37
+ runtime()
38
+ super().run()
39
+
40
+
41
+ class PlatformWheel(bdist_wheel):
42
+ def finalize_options(self):
43
+ super().finalize_options()
44
+ self.root_is_pure = False
45
+
46
+ def get_tag(self):
47
+ return "py3", "none", runtime()
48
+
49
+
50
+ class BinaryDistribution(Distribution):
51
+ def has_ext_modules(self):
52
+ return True
53
+
54
+
55
+ setup(distclass=BinaryDistribution, cmdclass={"build_py":BuildPython,"bdist_wheel":PlatformWheel})
@@ -0,0 +1,110 @@
1
+ Metadata-Version: 2.4
2
+ Name: worktrust
3
+ Version: 0.10.13
4
+ Summary: The WorkTrust CLI, using the same measurement engine as npm
5
+ License-Expression: MIT
6
+ Project-URL: Homepage, https://worktrust.io
7
+ Project-URL: Source, https://github.com/fhomey/worktrust-cli
8
+ Requires-Python: >=3.10
9
+ Description-Content-Type: text/markdown
10
+ License-File: LICENSE
11
+ Dynamic: license-file
12
+
13
+ # WorkTrust for Python tool runners
14
+
15
+ This package launches the same JavaScript measurement engine shipped in the WorkTrust npm
16
+ package. It does not implement another measurement engine or a Python instrumentation SDK.
17
+ Python 3.10+ is required. Supported platform wheels include **Node.js 22.23.3**; no separate
18
+ Node or npm installation is needed. The launcher uses that bundled runtime, never downloads a
19
+ runtime when invoked, and does not silently switch to another CLI version.
20
+
21
+ Wheels target macOS 11+ (Intel and Apple Silicon), Linux with glibc 2.28+ (x64 and arm64), and
22
+ Windows 10+ (x64 and arm64). Linux also requires the Node-supported system C++ runtime
23
+ (GLIBCXX_3.4.25 or newer). Alpine/musl, 32-bit systems and other platforms are not supported.
24
+ A source distribution cannot fetch Node automatically: a source build requires the explicit
25
+ maintainer preparation step below. Supported users should install the matching wheel.
26
+
27
+ After publication under a verified WorkTrust-owned PyPI project, the intended commands are:
28
+
29
+ ```sh
30
+ uvx worktrust preserve
31
+ pipx run worktrust preserve
32
+ ```
33
+
34
+ These public commands are not a claim that this package has already been published. Test a
35
+ reviewed local wheel first:
36
+
37
+ ```sh
38
+ uvx --from /absolute/path/worktrust-VERSION-py3-none-PLATFORM.whl worktrust --help
39
+ pipx run --spec /absolute/path/worktrust-VERSION-py3-none-PLATFORM.whl worktrust --help
40
+ ```
41
+
42
+ Use your package manager to choose and update the installed version. The package contains
43
+ the CLI modules and Node runtime, so `preserve` itself needs no network after installation. It reads supported
44
+ local session files and can change retention settings or create local metadata archives;
45
+ only the person runs it. Existing WorkTrust agent safeguards and consent prompts remain.
46
+ Other commands can contact WorkTrust. Package installation itself can contact registries.
47
+
48
+ After PyPI publication, explicitly request the latest published package when needed:
49
+
50
+ ```sh
51
+ uvx worktrust@latest preserve
52
+ pipx run --no-cache worktrust preserve
53
+ ```
54
+
55
+ For persistent installations, use `uv tool upgrade worktrust` or `pipx upgrade worktrust`.
56
+ An existing cache or version constraint can otherwise keep an older release. `worktrust update`
57
+ refreshes the computer coupling using the selected package; it does not upgrade the Python package.
58
+
59
+ Runtime bundle hashes detect missing or changed files; they are not hardware attestation or
60
+ independent proof of authenticity. Request and archive signatures retain the existing CLI's
61
+ software-key threat model. See the npm package SECURITY.md and README.md for the data contract.
62
+
63
+ ## Maintainers
64
+
65
+ Running `node tools/worktrust-cli/sync.mjs` from the monorepo also regenerates the Python JavaScript
66
+ bundle and version. `node scripts/build-python-cli.mjs --check` refuses drift. The native runtime
67
+ is a separate build artifact, excluded from Git and sdists. Explicitly prepare it before building:
68
+
69
+ ```sh
70
+ python tools/worktrust-python/build_runtime.py
71
+ python -m build --wheel tools/worktrust-python
72
+ python -m build --sdist tools/worktrust-python
73
+ ```
74
+
75
+ `build_runtime.py` downloads one official Node archive from nodejs.org at build time, verifies its
76
+ committed SHA256 from `runtime-lock.json`, and extracts only the executable and complete LICENSE.
77
+ It accepts `--target` for a reviewed target and `--cache` for a build cache. Platform wheel tags
78
+ follow the selected runtime. Never label these wheels `any`. Building a wheel from the sdist
79
+ fails closed until this explicit preparation step has been performed; no install hook downloads code.
80
+
81
+ Run `python tools/worktrust-python/tests/test_runtime_build.py`, then
82
+ `node scripts/test-python-cli.mjs` with a Python containing the build requirements (select it with
83
+ `WORKTRUST_TEST_PYTHON`). Tests build and exercise a real wheel using its own runtime with no Node
84
+ on PATH; they use synthetic homes and metadata only. Native execution must pass independently on
85
+ all six claimed OS/architecture combinations before release. Cross-building alone is not that proof.
86
+ Set `WORKTRUST_REQUIRE_TOOL_RUNNERS=1` to require actual uv and pipx wheel smoke tests, and
87
+ `WORKTRUST_TEST_ARTIFACT_DIR` to a fresh directory to retain the exact tested wheel and sdist.
88
+ Existing artifacts are never overwritten. Canonical module bytes match across channels;
89
+ bit-for-bit reproducibility of whole wheel or sdist archives is not asserted.
90
+
91
+ The public `fhomey/worktrust-cli` repository carries this package under `python/`, alongside the
92
+ npm package at its root. There, install `python/requirements-release.txt`, run
93
+ `python python/build_runtime.py`, then `python python/tests/test_distribution.py` with
94
+ `WORKTRUST_TEST_CLI_SOURCE` set to the repository's absolute path and
95
+ `WORKTRUST_REQUIRE_TOOL_RUNNERS=1`. The test derives Node from the built wheel; it does not require
96
+ a system Node installation. Keep build-only workflow results distinct from successful publication.
97
+
98
+ The inactive `release-pypi.yml.example` targets this public layout. Its intended active filename
99
+ is `.github/workflows/release-pypi.yml`, using the protected `pypi` environment and PyPI Trusted
100
+ Publishing. Once activated, the same GitHub release triggers both registries; manual execution
101
+ supports the initial Python publication and retries. npm also requires the supported-platform Python
102
+ artifact/parity tests before publishing. Both channels use the same version and module bytes.
103
+ Approvals and registry failures remain separate; confirm both publications before announcing a
104
+ release as available on both channels. Neither workflow invokes a Vercel deployment.
105
+
106
+ Do not edit generated `bundle/`, `VERSION` or `LICENSE`. Publication requires confirmed
107
+ PyPI ownership and a configured Trusted Publisher; source readiness does not grant that.
108
+
109
+ Official runtime platform requirements: https://github.com/nodejs/node/blob/v22.23.3/BUILDING.md
110
+ Pinned upstream archive checksums: https://nodejs.org/dist/v22.23.3/SHASUMS256.txt
@@ -0,0 +1,32 @@
1
+ LICENSE
2
+ MANIFEST.in
3
+ README.md
4
+ VERSION
5
+ build_runtime.py
6
+ pyproject.toml
7
+ runtime-lock.json
8
+ setup.py
9
+ src/worktrust.egg-info/PKG-INFO
10
+ src/worktrust.egg-info/SOURCES.txt
11
+ src/worktrust.egg-info/dependency_links.txt
12
+ src/worktrust.egg-info/entry_points.txt
13
+ src/worktrust.egg-info/top_level.txt
14
+ src/worktrust_cli/__init__.py
15
+ src/worktrust_cli/__main__.py
16
+ src/worktrust_cli/bundle/chat-exports.mjs
17
+ src/worktrust_cli/bundle/config-edits.mjs
18
+ src/worktrust_cli/bundle/count-behaviour.mjs
19
+ src/worktrust_cli/bundle/log-session.mjs
20
+ src/worktrust_cli/bundle/manifest.json
21
+ src/worktrust_cli/bundle/preserve-lines.mjs
22
+ src/worktrust_cli/bundle/preserve-summary.mjs
23
+ src/worktrust_cli/bundle/preserve.mjs
24
+ src/worktrust_cli/bundle/runtime-install.mjs
25
+ src/worktrust_cli/bundle/session-databases.mjs
26
+ src/worktrust_cli/bundle/setup-mcp.mjs
27
+ src/worktrust_cli/bundle/stack-rules.mjs
28
+ src/worktrust_cli/bundle/stretch-evidence.mjs
29
+ src/worktrust_cli/bundle/transcript-readers.mjs
30
+ src/worktrust_cli/bundle/worktrust.mjs
31
+ tests/test_distribution.py
32
+ tests/test_runtime_build.py
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ worktrust = worktrust_cli:main
@@ -0,0 +1 @@
1
+ worktrust_cli