Jarvis-Forge 1.0.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 (39) hide show
  1. jarvis_forge-1.0.0/CHANGELOG.md +49 -0
  2. jarvis_forge-1.0.0/LICENSE +22 -0
  3. jarvis_forge-1.0.0/MANIFEST.in +16 -0
  4. jarvis_forge-1.0.0/PKG-INFO +213 -0
  5. jarvis_forge-1.0.0/README.md +184 -0
  6. jarvis_forge-1.0.0/pyproject.toml +45 -0
  7. jarvis_forge-1.0.0/setup.cfg +4 -0
  8. jarvis_forge-1.0.0/src/Jarvis_Forge.egg-info/PKG-INFO +213 -0
  9. jarvis_forge-1.0.0/src/Jarvis_Forge.egg-info/SOURCES.txt +37 -0
  10. jarvis_forge-1.0.0/src/Jarvis_Forge.egg-info/dependency_links.txt +1 -0
  11. jarvis_forge-1.0.0/src/Jarvis_Forge.egg-info/entry_points.txt +2 -0
  12. jarvis_forge-1.0.0/src/Jarvis_Forge.egg-info/requires.txt +11 -0
  13. jarvis_forge-1.0.0/src/Jarvis_Forge.egg-info/top_level.txt +1 -0
  14. jarvis_forge-1.0.0/src/jarvis_forge/__init__.py +4 -0
  15. jarvis_forge-1.0.0/src/jarvis_forge/__main__.py +4 -0
  16. jarvis_forge-1.0.0/src/jarvis_forge/apt_cli.py +234 -0
  17. jarvis_forge-1.0.0/src/jarvis_forge/catalog.py +171 -0
  18. jarvis_forge-1.0.0/src/jarvis_forge/cli.py +354 -0
  19. jarvis_forge-1.0.0/src/jarvis_forge/comparison.py +90 -0
  20. jarvis_forge-1.0.0/src/jarvis_forge/downloads.py +87 -0
  21. jarvis_forge-1.0.0/src/jarvis_forge/env_cli.py +65 -0
  22. jarvis_forge-1.0.0/src/jarvis_forge/environment.py +158 -0
  23. jarvis_forge-1.0.0/src/jarvis_forge/environment_registry.py +252 -0
  24. jarvis_forge-1.0.0/src/jarvis_forge/examples/smoke.yaml +24 -0
  25. jarvis_forge-1.0.0/src/jarvis_forge/official.py +366 -0
  26. jarvis_forge-1.0.0/src/jarvis_forge/packages.py +498 -0
  27. jarvis_forge-1.0.0/src/jarvis_forge/recipes/eigen.yaml +22 -0
  28. jarvis_forge-1.0.0/src/jarvis_forge/recipes/redis.yaml +20 -0
  29. jarvis_forge-1.0.0/src/jarvis_forge/runner.py +203 -0
  30. jarvis_forge-1.0.0/src/jarvis_forge/schemas/recipe.schema.json +46 -0
  31. jarvis_forge-1.0.0/src/jarvis_forge/schemas/suite.schema.json +143 -0
  32. jarvis_forge-1.0.0/src/jarvis_forge/storage.py +151 -0
  33. jarvis_forge-1.0.0/src/jarvis_forge/suite.py +144 -0
  34. jarvis_forge-1.0.0/tests/test_apt.py +346 -0
  35. jarvis_forge-1.0.0/tests/test_cli.py +89 -0
  36. jarvis_forge-1.0.0/tests/test_env_registry.py +235 -0
  37. jarvis_forge-1.0.0/tests/test_environment.py +126 -0
  38. jarvis_forge-1.0.0/tests/test_official.py +252 -0
  39. jarvis_forge-1.0.0/tests/test_workflow.py +212 -0
@@ -0,0 +1,49 @@
1
+ # Changelog
2
+
3
+ ## 1.0.0
4
+
5
+ ### Added
6
+
7
+ - Provide the independent `jforge` CLI for user-space package installation, environment inspection and command-based acceptance workflows, with structured JSON output.
8
+ - Keep software receipts, named environments and run history in one shared user directory, independent of the Python installation running Forge.
9
+ - Install, reinstall, remove and upgrade source packages under private user prefixes with `jforge apt`; include pinned Eigen and Redis recipes, version constraints, dependency resolution and activation scripts.
10
+ - Import Debian and Ubuntu source metadata and quilt patches through reviewed build adapters, then track upstream versions and packaging revisions with `apt update` and `apt upgrade`.
11
+ - Register, list and inspect named environments with `env add/list/show`; preserve private shell copies and immutable revisions, with explicit executable or pyenv selections through `env set-python`.
12
+ - Inspect compiler paths and versions, Python interpreters and packages, and selected pyenv/module variables with `doctor`; select a registered environment explicitly using `--env` or acceptance YAML.
13
+ - Run versioned YAML command suites with step dependencies, environment scripts, explicit working directories, timeouts, process cleanup and declared output checks.
14
+ - Archive suite configurations, inputs, commands, activated environments, stdout/stderr, exit status and output files for each run; query history and compare recorded evidence with `compare` and `compare --check`.
15
+
16
+ ### Compatibility and upgrade notes
17
+
18
+ - Forge requires Python 3.10 or newer and a POSIX system with Bash. Use existing compiler tools, site modules and pyenv environments; target Python environments do not need Forge installed.
19
+ - Environment selection is explicit. `${python}` refers to Forge's own interpreter; use `python` or `python3` for the interpreter selected by an environment script or named environment.
20
+ - Existing prototype user directories remain in use. Comparisons include activated tool and Python versions; missing activation evidence makes a comparison not comparable.
21
+ - Package installation uses recipe-defined source builds. Bundled official-source adapters cover Eigen and Redis; other imports may require a reviewed recipe. Official metadata uses HTTPS and checksum verification by default; provide `--keyring` to require archive-signature verification.
22
+ - Commands run locally in the foreground. Slurm submission, SSH-disconnect recovery, automatic service management and scientific comparison policies are not included. Installing Redis does not start a server.
23
+
24
+ ## 0.1.2
25
+
26
+ - Import and track source metadata from official Debian and Ubuntu repositories.
27
+ - Refresh tracked recipes with `apt update` and detect Debian patch/revision changes with `apt upgrade`.
28
+ - Preserve and apply quilt patch series before building source packages into user prefixes.
29
+ - Record repository origin, suite, source versions, index/archive checksums and signature-verification status.
30
+ - Keep unsupported imports pending and save standard CMake/configure drafts without activating them.
31
+
32
+ ## 0.1.1
33
+
34
+ - Add the user-local `jforge apt` command group with catalog search, package details, installation, reinstall, removal, autoremove, source updates, upgrades and version constraints.
35
+ - Bundle pinned Eigen and Redis source recipes and support local and HTTPS recipe indexes.
36
+ - Verify archive checksums, reject unsafe archive entries, resolve recipe dependencies and record real installations under user prefixes.
37
+ - Generate versioned activation scripts and preserve working instances across failed builds and upgrades.
38
+ - Record source recipes, commands, stdout/stderr, checks and removed receipts for package operations.
39
+
40
+ ## 0.1.0
41
+
42
+ - Create the independent Jarvis-Forge distribution and `jforge` CLI.
43
+ - Add private user-directory initialization, tool discovery and package-manifest queries.
44
+ - Validate versioned YAML command suites and preview execution without running commands.
45
+ - Execute local acceptance steps with dependency ordering, environment scripts, timeouts and process-group cleanup.
46
+ - Preserve configuration, commands, input snapshots, stdout/stderr, exit status and output artifacts for every run.
47
+ - Query run history and compare archived evidence without repeating tests.
48
+ - Bundle a Python-only smoke suite and a host CLI integration entry point.
49
+
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Jarvis-Forge Developers
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
+
@@ -0,0 +1,16 @@
1
+ include CHANGELOG.md
2
+ recursive-include tests *.py
3
+
4
+ # Git ignores do not control source distributions.
5
+ exclude jfrel
6
+ prune .github
7
+ prune .agents
8
+ prune .codex
9
+ prune .claude
10
+ prune .venv
11
+ prune .pytest_cache
12
+ prune .aws
13
+ prune .ssh
14
+ prune .pypi
15
+ prune .twine
16
+ global-exclude .DS_Store *.py[cod] .env .env.* .envrc .pypirc .pypirc.* .twinerc .pypi-token* release.env twine.env
@@ -0,0 +1,213 @@
1
+ Metadata-Version: 2.4
2
+ Name: Jarvis-Forge
3
+ Version: 1.0.0
4
+ Summary: User-space environments and reproducible command acceptance runs for scientific software
5
+ Author: Jarvis-Forge Developers
6
+ License-Expression: MIT
7
+ Project-URL: Repository, https://github.com/Pengxuan-Zhu-Phys/Jarvis-Forge
8
+ Project-URL: Issues, https://github.com/Pengxuan-Zhu-Phys/Jarvis-Forge/issues
9
+ Project-URL: Documentation, https://github.com/Pengxuan-Zhu-Phys/Jarvis-Books/tree/main/Docs/Jarvis-Forge
10
+ Classifier: Development Status :: 5 - Production/Stable
11
+ Classifier: Environment :: Console
12
+ Classifier: Operating System :: POSIX
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Topic :: Software Development :: Testing
15
+ Requires-Python: >=3.10
16
+ Description-Content-Type: text/markdown
17
+ License-File: LICENSE
18
+ Requires-Dist: typer>=0.16
19
+ Requires-Dist: click>=8.1
20
+ Requires-Dist: rich>=13
21
+ Requires-Dist: PyYAML>=6
22
+ Requires-Dist: jsonschema>=4.18
23
+ Requires-Dist: packaging>=23
24
+ Provides-Extra: dev
25
+ Requires-Dist: pytest>=7; extra == "dev"
26
+ Requires-Dist: build>=1; extra == "dev"
27
+ Requires-Dist: twine>=6; extra == "dev"
28
+ Dynamic: license-file
29
+
30
+ # Jarvis-Forge
31
+
32
+ Jarvis-Forge is an independent Python package for user-space software environments and command-based acceptance workflows on scientific workstations and HPC systems. Its CLI is `jforge`.
33
+
34
+ Forge runs local command suites and preserves their evidence. Its `jforge apt` command downloads, verifies and builds recipe-defined software into private user prefixes. Named environments keep private, versioned shell copies and explicit target Python selections in one shared user directory. Managed services, Slurm submission, scientific comparison policies, and the `Jarvis forge` forwarding command are planned extensions.
35
+
36
+ ## Install
37
+
38
+ Python 3.10 or newer and a POSIX system with Bash are required for execution. Use WSL on Windows. Forge does not depend on Jarvis-HEP.
39
+
40
+ ```bash
41
+ python3 -m pip install Jarvis-Forge
42
+ jforge --version
43
+ jforge --help
44
+ ```
45
+
46
+ The distribution name is `Jarvis-Forge`. For development from a checkout:
47
+
48
+ ```bash
49
+ python3 -m pip install -e '.[dev]'
50
+ ```
51
+
52
+ Build source and wheel distributions with:
53
+
54
+ ```bash
55
+ python3 -m build
56
+ ```
57
+
58
+ ## Try the acceptance workflow
59
+
60
+ These commands create a private Forge user directory under the current directory and write a smoke-suite YAML. The demo uses Python only; it does not download software or start services.
61
+
62
+ ```bash
63
+ jforge --home .forge-home init
64
+ jforge example --output smoke.yaml
65
+ jforge validate smoke.yaml
66
+ jforge plan smoke.yaml
67
+ jforge --home .forge-home run smoke.yaml
68
+ jforge --home .forge-home run smoke.yaml
69
+ jforge --home .forge-home history --suite forge-smoke
70
+ ```
71
+
72
+ Copy the run IDs printed by `run` or listed by `history`:
73
+
74
+ ```bash
75
+ jforge --home .forge-home show <run-id>
76
+ jforge --home .forge-home logs <run-id> --step calculate
77
+ jforge --home .forge-home compare <older-run-id> <newer-run-id>
78
+ ```
79
+
80
+ `--json`, `--home` and `--debug` work before or after the command. `--json` emits one JSON object on stdout, while progress goes to stderr. `compare --check` fails on changed, missing, corrupted or unsuccessful evidence; ordinary comparison only describes differences. Comparison uses exact artifact bytes; scientific equivalence and performance regression policies remain outside the current comparison mode.
81
+
82
+ ## User directories and package queries
83
+
84
+ Forge uses `~/.jarvis-forge` by default. `--home` overrides `JFORGE_HOME`, which overrides that default. `paths`, `doctor`, `list`, `info`, `validate`, `plan`, `history`, `show` and `logs` do not initialize a user directory or install software.
85
+
86
+ ```bash
87
+ jforge paths
88
+ jforge doctor
89
+ jforge doctor --shell /path/to/cbs-env.sh
90
+ jforge doctor --shell /path/to/cbs-env.sh --json
91
+ jforge list
92
+ jforge info eigen
93
+ jforge info eigen --package-version 3.4.0 --instance <install-id> --path
94
+ ```
95
+
96
+ `info` queries JSON installation manifests under `packages/<name>/<version>/<install-id>/manifest.json`. `jforge apt install` creates those records after installation checks pass. Multiple instances are listed explicitly; `--path` requires a unique match. `--package-version` selects installed software; `--version` remains Forge's version query.
97
+
98
+ You select and prepare Python environments with pyenv or your existing tools. `doctor --shell` sources your trusted Bash script and reports the resulting CC/CXX/FC selections, compiler and build-tool paths and versions, Python interpreter paths and versions, virtual environment prefixes, installed Python packages, and selected module/pyenv variables. It does not choose an environment or switch to a fallback. Without `--shell`, it inspects the inherited environment. Missing tools and failed version probes are reported individually; activation errors fail the command. `--timeout` limits the complete inspection, including activation. Shell output is kept separate from JSON results. Inspection creates no Forge user state.
99
+
100
+ ## Named environments and target Python
101
+
102
+ All Forge installations for the same user share `~/.jarvis-forge`, independently of the Python version running the CLI. `JFORGE_HOME` and `--home` can explicitly select a different store. Target Python environments do not need Forge installed.
103
+
104
+ ```bash
105
+ jforge env add cbs --shell /path/to/cbs-env.sh
106
+ jforge env list
107
+ jforge env show cbs
108
+ jforge env show cbs --path
109
+ jforge env set-python cbs --python /path/to/existing/venv/bin/python
110
+ # Alternatively, select an existing pyenv environment:
111
+ jforge env set-python cbs --pyenv cbs-python
112
+ jforge doctor --env cbs
113
+ jforge run acceptance.yaml --env cbs
114
+ ```
115
+
116
+ `env add` copies the script into `environments/<name>/revisions/<revision>/source.sh` and generates `activate.sh`. It checks Bash syntax without sourcing the script. Registration and Python configuration do not activate an environment in your current shell or set a default for later runs. Choose a profile explicitly with `--env`, `environment.name` in YAML, or `source "$(jforge env show cbs --path)"` in your own shell.
117
+
118
+ `set-python` changes the target Python for that named environment only. Use `--python` for an existing executable, or `--pyenv` for one existing pyenv version/environment; `--pyenv-root` locates non-default version storage. Forge records the actual pyenv program separately from its storage root, supporting package-manager installations. It does not install Python, change pyenv global/local settings, or switch the interpreter running Forge. `--inherit` removes the Python override and uses the script's PATH again. When overridden, both `python` and `python3` use the chosen interpreter; the configured environment's bin directory is also put on PATH.
119
+
120
+ Every `env add ... --replace` or `set-python` saves a new revision and preserves previous scripts. Use `env show cbs --revision <revision>` to inspect an older revision. `env list/show` do not execute scripts. Missing or modified managed files are reported and cannot be selected for execution. Runs archive the chosen revision, original script copy and generated wrappers. The reserved `apt` environment appears in the list after package activation and remains managed by `jforge apt`.
121
+
122
+ Scripts are copied, not relocated together with their dependencies: use stable absolute paths for external files. If the original script changes, register the update with `env add cbs --shell /path/to/cbs-env.sh --replace`. For reproducibility, files in published revisions are not intended for direct editing. Full usage and storage details are in [the environment guide](https://github.com/Pengxuan-Zhu-Phys/Jarvis-Books/blob/main/Docs/Jarvis-Forge/ENVIRONMENTS.md).
123
+
124
+ ## User-local package manager
125
+
126
+ `jforge apt` follows familiar apt command names and operates on Forge recipes and user prefixes. It does not invoke system apt, request sudo, or edit shell startup files. Official source-package metadata can be tracked through `apt import`.
127
+
128
+ ```bash
129
+ jforge apt --help
130
+ jforge apt update
131
+ jforge apt search eigen
132
+ jforge apt show eigen
133
+ jforge apt install eigen redis --jobs 2
134
+ jforge apt list --installed
135
+ jforge info eigen
136
+ source "$(jforge apt env --path)"
137
+ redis-server --version
138
+ ```
139
+
140
+ Bundled recipes pin Eigen 3.4.0 and Redis 7.2.17 to official source archives and SHA-256 checksums. Eigen needs CMake and C/C++ compilers; Redis needs make and a C compiler. Use your site's existing modules for build tools. Installs do not start a Redis server.
141
+
142
+ ```bash
143
+ jforge apt install eigen=3.4.0 --dry-run
144
+ jforge apt satisfy 'eigen>=3.4' --dry-run
145
+ jforge apt reinstall eigen
146
+ jforge apt upgrade --dry-run
147
+ jforge apt full-upgrade --dry-run
148
+ jforge apt remove eigen=3.4.0 --dry-run
149
+ jforge apt remove eigen=3.4.0 --yes
150
+ jforge apt autoremove --dry-run
151
+ ```
152
+
153
+ Every successful instance gets an immutable receipt and activation script; source downloads, recipe snapshots, command logs and checks live in the operation record. Reinstall and upgrade create separate prefixes and preserve old instances. Build or check failure leaves the previous active environment selected. Valid dependencies completed before a later package fails can remain as inactive installations.
154
+
155
+ The catalog contains only configured recipes. Add your own `recipes/*.yaml`, or register a local recipe directory/file or HTTPS YAML index, then refresh it:
156
+
157
+ ```bash
158
+ jforge apt edit-sources --add /path/to/recipes
159
+ jforge apt update
160
+ ```
161
+
162
+ Bundled recipes change with Forge releases; `update` refreshes configured external sources. `upgrade` resolves newer compatible versions from that catalog. `full-upgrade` uses the same source-recipe resolver and retains old instances; it performs no system-wide removals. Recipe commands are trusted build instructions, not sandboxed code. See the [package manager design and recipe format](https://github.com/Pengxuan-Zhu-Phys/Jarvis-Books/blob/main/Docs/Jarvis-Forge/APT.md).
163
+
164
+ ### Track official Debian and Ubuntu source packages
165
+
166
+ ```bash
167
+ jforge apt import libeigen3-dev --origin debian --suite bookworm --name eigen
168
+ jforge apt update
169
+ jforge apt list --upgradable
170
+ jforge apt upgrade --dry-run
171
+ jforge apt upgrade
172
+ ```
173
+
174
+ Import maps a binary or source package name through the official `Sources` index, records source versions and SHA-256, and preserves Debian quilt patches. A reviewed Forge template supplies user-prefix build options and checks. Built-in source adapters cover Eigen and Redis; `--template NAME` reuses a custom Forge recipe. Ubuntu sources use `--origin ubuntu --suite <codename>`.
175
+
176
+ `update` refreshes these tracked imports without compiling. `upgrade` detects both upstream changes and Debian revision/patch changes, creates new instances, and keeps old ones. Identical official metadata does not force a rebuild. Packages without an adapter are reported as pending; standard CMake/configure layouts receive a draft YAML for review. Drafts do not enter the install catalog or silently become valid updates. Debian Build-Depends fields are retained in the report; they are not blindly translated into Forge dependencies.
177
+
178
+ Default metadata trust is official HTTPS plus Release/index/archive checksums, reported as `apt_signature_verified: false`. To require archive-signature verification, supply `--keyring /path/to/trusted-archive-keyring.gpg`; this requires `gpgv` and fails if verification cannot be completed. The importer builds upstream projects with quilt patches; it does not execute `debian/rules` or reproduce the full Debian binary-package build.
179
+
180
+ ## Suite format
181
+
182
+ Suites use `schema_version: 1`, a stable `id`, and ordered command steps. Each step chooses either `argv` or an explicit Bash `script`, with optional `needs`, `cwd`, `timeout_seconds`, `expect_exit_code` and required `artifacts`. Commands and scripts are trusted user code.
183
+
184
+ The default working directory is the run's shared `workspace/`. Declared artifacts are relative file paths within the step's working directory; each is copied into the run archive. Supported placeholders are `${python}`, `${suite_dir}`, `${run_dir}`, `${step_dir}` and `${input:name}`. Inputs are declared as named file paths relative to the suite file and copied before execution.
185
+
186
+ Use `environment.name: cbs` to select a registered environment, optionally pinned with `environment.revision`. A CLI `--env` explicitly overrides the suite selection and uses the named environment's current revision. Alternatively, `environment.shell` points to a Bash script, relative to the suite file. These two YAML selections are mutually exclusive. It is snapshotted and sourced before each command, in the same shell. `environment.variables` supplies string-valued variables. The recorded plan and raw logs may include values supplied by the user; keep credentials out of suite files and command arguments.
187
+
188
+ The script must initialize your selected environment in a noninteractive Bash; login shell startup files are not loaded. Different suites may select different scripts. For example:
189
+
190
+ ```yaml
191
+ schema_version: 1
192
+ id: cbs-environment
193
+ environment:
194
+ shell: ./cbs-env.sh
195
+ steps:
196
+ - id: python
197
+ argv: [python, --version]
198
+ ```
199
+
200
+ Use `python` or `python3` for the interpreter selected by that script. `${python}` always refers to the interpreter running Forge itself, which can be different. Each executed step saves `activation.json` and includes its environment report in `show --step`; reports contain actual tool versions and target Python package inventories. Comparisons include these activated environments, so changing a compiler or Python environment is visible even when commands and script contents are unchanged. Missing activation records make the affected comparison not comparable. Version probes do not compile code or establish that dependencies meet a particular project's requirements.
201
+
202
+ Every run has a new ID and saves configuration, environment observations, actual commands, activation details, logs, exit status, elapsed time, and declared output files. Source code and arbitrary undeclared outputs are not archived automatically. These records support comparison; they are not a complete machine image or automatic source backup. Failed prerequisites block dependent steps; independent steps continue. Foreground execution does not promise survival after SSH disconnection.
203
+
204
+ ## Development and integration
205
+
206
+ ```bash
207
+ python3 -m pytest
208
+ ```
209
+
210
+ The host integration point is `jarvis_forge.cli.main(argv, prog="Jarvis forge")`; it returns an exit code and owns the single parser. The standalone console script is operational. Jarvis-HEP forwarding is not yet integrated.
211
+
212
+ Project design and implementation scope live in [Jarvis-Books](https://github.com/Pengxuan-Zhu-Phys/Jarvis-Books/tree/main/Docs/Jarvis-Forge). CLI behavior follows the [Jarvis ecosystem CLI specification](https://github.com/Pengxuan-Zhu-Phys/Jarvis-Books/blob/main/Docs/Ecosystem/JARVIS_CLI_DESIGN.md).
213
+
@@ -0,0 +1,184 @@
1
+ # Jarvis-Forge
2
+
3
+ Jarvis-Forge is an independent Python package for user-space software environments and command-based acceptance workflows on scientific workstations and HPC systems. Its CLI is `jforge`.
4
+
5
+ Forge runs local command suites and preserves their evidence. Its `jforge apt` command downloads, verifies and builds recipe-defined software into private user prefixes. Named environments keep private, versioned shell copies and explicit target Python selections in one shared user directory. Managed services, Slurm submission, scientific comparison policies, and the `Jarvis forge` forwarding command are planned extensions.
6
+
7
+ ## Install
8
+
9
+ Python 3.10 or newer and a POSIX system with Bash are required for execution. Use WSL on Windows. Forge does not depend on Jarvis-HEP.
10
+
11
+ ```bash
12
+ python3 -m pip install Jarvis-Forge
13
+ jforge --version
14
+ jforge --help
15
+ ```
16
+
17
+ The distribution name is `Jarvis-Forge`. For development from a checkout:
18
+
19
+ ```bash
20
+ python3 -m pip install -e '.[dev]'
21
+ ```
22
+
23
+ Build source and wheel distributions with:
24
+
25
+ ```bash
26
+ python3 -m build
27
+ ```
28
+
29
+ ## Try the acceptance workflow
30
+
31
+ These commands create a private Forge user directory under the current directory and write a smoke-suite YAML. The demo uses Python only; it does not download software or start services.
32
+
33
+ ```bash
34
+ jforge --home .forge-home init
35
+ jforge example --output smoke.yaml
36
+ jforge validate smoke.yaml
37
+ jforge plan smoke.yaml
38
+ jforge --home .forge-home run smoke.yaml
39
+ jforge --home .forge-home run smoke.yaml
40
+ jforge --home .forge-home history --suite forge-smoke
41
+ ```
42
+
43
+ Copy the run IDs printed by `run` or listed by `history`:
44
+
45
+ ```bash
46
+ jforge --home .forge-home show <run-id>
47
+ jforge --home .forge-home logs <run-id> --step calculate
48
+ jforge --home .forge-home compare <older-run-id> <newer-run-id>
49
+ ```
50
+
51
+ `--json`, `--home` and `--debug` work before or after the command. `--json` emits one JSON object on stdout, while progress goes to stderr. `compare --check` fails on changed, missing, corrupted or unsuccessful evidence; ordinary comparison only describes differences. Comparison uses exact artifact bytes; scientific equivalence and performance regression policies remain outside the current comparison mode.
52
+
53
+ ## User directories and package queries
54
+
55
+ Forge uses `~/.jarvis-forge` by default. `--home` overrides `JFORGE_HOME`, which overrides that default. `paths`, `doctor`, `list`, `info`, `validate`, `plan`, `history`, `show` and `logs` do not initialize a user directory or install software.
56
+
57
+ ```bash
58
+ jforge paths
59
+ jforge doctor
60
+ jforge doctor --shell /path/to/cbs-env.sh
61
+ jforge doctor --shell /path/to/cbs-env.sh --json
62
+ jforge list
63
+ jforge info eigen
64
+ jforge info eigen --package-version 3.4.0 --instance <install-id> --path
65
+ ```
66
+
67
+ `info` queries JSON installation manifests under `packages/<name>/<version>/<install-id>/manifest.json`. `jforge apt install` creates those records after installation checks pass. Multiple instances are listed explicitly; `--path` requires a unique match. `--package-version` selects installed software; `--version` remains Forge's version query.
68
+
69
+ You select and prepare Python environments with pyenv or your existing tools. `doctor --shell` sources your trusted Bash script and reports the resulting CC/CXX/FC selections, compiler and build-tool paths and versions, Python interpreter paths and versions, virtual environment prefixes, installed Python packages, and selected module/pyenv variables. It does not choose an environment or switch to a fallback. Without `--shell`, it inspects the inherited environment. Missing tools and failed version probes are reported individually; activation errors fail the command. `--timeout` limits the complete inspection, including activation. Shell output is kept separate from JSON results. Inspection creates no Forge user state.
70
+
71
+ ## Named environments and target Python
72
+
73
+ All Forge installations for the same user share `~/.jarvis-forge`, independently of the Python version running the CLI. `JFORGE_HOME` and `--home` can explicitly select a different store. Target Python environments do not need Forge installed.
74
+
75
+ ```bash
76
+ jforge env add cbs --shell /path/to/cbs-env.sh
77
+ jforge env list
78
+ jforge env show cbs
79
+ jforge env show cbs --path
80
+ jforge env set-python cbs --python /path/to/existing/venv/bin/python
81
+ # Alternatively, select an existing pyenv environment:
82
+ jforge env set-python cbs --pyenv cbs-python
83
+ jforge doctor --env cbs
84
+ jforge run acceptance.yaml --env cbs
85
+ ```
86
+
87
+ `env add` copies the script into `environments/<name>/revisions/<revision>/source.sh` and generates `activate.sh`. It checks Bash syntax without sourcing the script. Registration and Python configuration do not activate an environment in your current shell or set a default for later runs. Choose a profile explicitly with `--env`, `environment.name` in YAML, or `source "$(jforge env show cbs --path)"` in your own shell.
88
+
89
+ `set-python` changes the target Python for that named environment only. Use `--python` for an existing executable, or `--pyenv` for one existing pyenv version/environment; `--pyenv-root` locates non-default version storage. Forge records the actual pyenv program separately from its storage root, supporting package-manager installations. It does not install Python, change pyenv global/local settings, or switch the interpreter running Forge. `--inherit` removes the Python override and uses the script's PATH again. When overridden, both `python` and `python3` use the chosen interpreter; the configured environment's bin directory is also put on PATH.
90
+
91
+ Every `env add ... --replace` or `set-python` saves a new revision and preserves previous scripts. Use `env show cbs --revision <revision>` to inspect an older revision. `env list/show` do not execute scripts. Missing or modified managed files are reported and cannot be selected for execution. Runs archive the chosen revision, original script copy and generated wrappers. The reserved `apt` environment appears in the list after package activation and remains managed by `jforge apt`.
92
+
93
+ Scripts are copied, not relocated together with their dependencies: use stable absolute paths for external files. If the original script changes, register the update with `env add cbs --shell /path/to/cbs-env.sh --replace`. For reproducibility, files in published revisions are not intended for direct editing. Full usage and storage details are in [the environment guide](https://github.com/Pengxuan-Zhu-Phys/Jarvis-Books/blob/main/Docs/Jarvis-Forge/ENVIRONMENTS.md).
94
+
95
+ ## User-local package manager
96
+
97
+ `jforge apt` follows familiar apt command names and operates on Forge recipes and user prefixes. It does not invoke system apt, request sudo, or edit shell startup files. Official source-package metadata can be tracked through `apt import`.
98
+
99
+ ```bash
100
+ jforge apt --help
101
+ jforge apt update
102
+ jforge apt search eigen
103
+ jforge apt show eigen
104
+ jforge apt install eigen redis --jobs 2
105
+ jforge apt list --installed
106
+ jforge info eigen
107
+ source "$(jforge apt env --path)"
108
+ redis-server --version
109
+ ```
110
+
111
+ Bundled recipes pin Eigen 3.4.0 and Redis 7.2.17 to official source archives and SHA-256 checksums. Eigen needs CMake and C/C++ compilers; Redis needs make and a C compiler. Use your site's existing modules for build tools. Installs do not start a Redis server.
112
+
113
+ ```bash
114
+ jforge apt install eigen=3.4.0 --dry-run
115
+ jforge apt satisfy 'eigen>=3.4' --dry-run
116
+ jforge apt reinstall eigen
117
+ jforge apt upgrade --dry-run
118
+ jforge apt full-upgrade --dry-run
119
+ jforge apt remove eigen=3.4.0 --dry-run
120
+ jforge apt remove eigen=3.4.0 --yes
121
+ jforge apt autoremove --dry-run
122
+ ```
123
+
124
+ Every successful instance gets an immutable receipt and activation script; source downloads, recipe snapshots, command logs and checks live in the operation record. Reinstall and upgrade create separate prefixes and preserve old instances. Build or check failure leaves the previous active environment selected. Valid dependencies completed before a later package fails can remain as inactive installations.
125
+
126
+ The catalog contains only configured recipes. Add your own `recipes/*.yaml`, or register a local recipe directory/file or HTTPS YAML index, then refresh it:
127
+
128
+ ```bash
129
+ jforge apt edit-sources --add /path/to/recipes
130
+ jforge apt update
131
+ ```
132
+
133
+ Bundled recipes change with Forge releases; `update` refreshes configured external sources. `upgrade` resolves newer compatible versions from that catalog. `full-upgrade` uses the same source-recipe resolver and retains old instances; it performs no system-wide removals. Recipe commands are trusted build instructions, not sandboxed code. See the [package manager design and recipe format](https://github.com/Pengxuan-Zhu-Phys/Jarvis-Books/blob/main/Docs/Jarvis-Forge/APT.md).
134
+
135
+ ### Track official Debian and Ubuntu source packages
136
+
137
+ ```bash
138
+ jforge apt import libeigen3-dev --origin debian --suite bookworm --name eigen
139
+ jforge apt update
140
+ jforge apt list --upgradable
141
+ jforge apt upgrade --dry-run
142
+ jforge apt upgrade
143
+ ```
144
+
145
+ Import maps a binary or source package name through the official `Sources` index, records source versions and SHA-256, and preserves Debian quilt patches. A reviewed Forge template supplies user-prefix build options and checks. Built-in source adapters cover Eigen and Redis; `--template NAME` reuses a custom Forge recipe. Ubuntu sources use `--origin ubuntu --suite <codename>`.
146
+
147
+ `update` refreshes these tracked imports without compiling. `upgrade` detects both upstream changes and Debian revision/patch changes, creates new instances, and keeps old ones. Identical official metadata does not force a rebuild. Packages without an adapter are reported as pending; standard CMake/configure layouts receive a draft YAML for review. Drafts do not enter the install catalog or silently become valid updates. Debian Build-Depends fields are retained in the report; they are not blindly translated into Forge dependencies.
148
+
149
+ Default metadata trust is official HTTPS plus Release/index/archive checksums, reported as `apt_signature_verified: false`. To require archive-signature verification, supply `--keyring /path/to/trusted-archive-keyring.gpg`; this requires `gpgv` and fails if verification cannot be completed. The importer builds upstream projects with quilt patches; it does not execute `debian/rules` or reproduce the full Debian binary-package build.
150
+
151
+ ## Suite format
152
+
153
+ Suites use `schema_version: 1`, a stable `id`, and ordered command steps. Each step chooses either `argv` or an explicit Bash `script`, with optional `needs`, `cwd`, `timeout_seconds`, `expect_exit_code` and required `artifacts`. Commands and scripts are trusted user code.
154
+
155
+ The default working directory is the run's shared `workspace/`. Declared artifacts are relative file paths within the step's working directory; each is copied into the run archive. Supported placeholders are `${python}`, `${suite_dir}`, `${run_dir}`, `${step_dir}` and `${input:name}`. Inputs are declared as named file paths relative to the suite file and copied before execution.
156
+
157
+ Use `environment.name: cbs` to select a registered environment, optionally pinned with `environment.revision`. A CLI `--env` explicitly overrides the suite selection and uses the named environment's current revision. Alternatively, `environment.shell` points to a Bash script, relative to the suite file. These two YAML selections are mutually exclusive. It is snapshotted and sourced before each command, in the same shell. `environment.variables` supplies string-valued variables. The recorded plan and raw logs may include values supplied by the user; keep credentials out of suite files and command arguments.
158
+
159
+ The script must initialize your selected environment in a noninteractive Bash; login shell startup files are not loaded. Different suites may select different scripts. For example:
160
+
161
+ ```yaml
162
+ schema_version: 1
163
+ id: cbs-environment
164
+ environment:
165
+ shell: ./cbs-env.sh
166
+ steps:
167
+ - id: python
168
+ argv: [python, --version]
169
+ ```
170
+
171
+ Use `python` or `python3` for the interpreter selected by that script. `${python}` always refers to the interpreter running Forge itself, which can be different. Each executed step saves `activation.json` and includes its environment report in `show --step`; reports contain actual tool versions and target Python package inventories. Comparisons include these activated environments, so changing a compiler or Python environment is visible even when commands and script contents are unchanged. Missing activation records make the affected comparison not comparable. Version probes do not compile code or establish that dependencies meet a particular project's requirements.
172
+
173
+ Every run has a new ID and saves configuration, environment observations, actual commands, activation details, logs, exit status, elapsed time, and declared output files. Source code and arbitrary undeclared outputs are not archived automatically. These records support comparison; they are not a complete machine image or automatic source backup. Failed prerequisites block dependent steps; independent steps continue. Foreground execution does not promise survival after SSH disconnection.
174
+
175
+ ## Development and integration
176
+
177
+ ```bash
178
+ python3 -m pytest
179
+ ```
180
+
181
+ The host integration point is `jarvis_forge.cli.main(argv, prog="Jarvis forge")`; it returns an exit code and owns the single parser. The standalone console script is operational. Jarvis-HEP forwarding is not yet integrated.
182
+
183
+ Project design and implementation scope live in [Jarvis-Books](https://github.com/Pengxuan-Zhu-Phys/Jarvis-Books/tree/main/Docs/Jarvis-Forge). CLI behavior follows the [Jarvis ecosystem CLI specification](https://github.com/Pengxuan-Zhu-Phys/Jarvis-Books/blob/main/Docs/Ecosystem/JARVIS_CLI_DESIGN.md).
184
+
@@ -0,0 +1,45 @@
1
+ [build-system]
2
+ requires = ["setuptools>=77", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "Jarvis-Forge"
7
+ dynamic = ["version"]
8
+ description = "User-space environments and reproducible command acceptance runs for scientific software"
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ license = "MIT"
12
+ authors = [{name = "Jarvis-Forge Developers"}]
13
+ classifiers = [
14
+ "Development Status :: 5 - Production/Stable",
15
+ "Environment :: Console",
16
+ "Operating System :: POSIX",
17
+ "Programming Language :: Python :: 3",
18
+ "Topic :: Software Development :: Testing",
19
+ ]
20
+ dependencies = ["typer>=0.16", "click>=8.1", "rich>=13", "PyYAML>=6", "jsonschema>=4.18", "packaging>=23"]
21
+
22
+ [project.optional-dependencies]
23
+ dev = ["pytest>=7", "build>=1", "twine>=6"]
24
+
25
+ [project.scripts]
26
+ jforge = "jarvis_forge.cli:main"
27
+
28
+ [project.urls]
29
+ Repository = "https://github.com/Pengxuan-Zhu-Phys/Jarvis-Forge"
30
+ Issues = "https://github.com/Pengxuan-Zhu-Phys/Jarvis-Forge/issues"
31
+ Documentation = "https://github.com/Pengxuan-Zhu-Phys/Jarvis-Books/tree/main/Docs/Jarvis-Forge"
32
+
33
+ [tool.setuptools.dynamic]
34
+ version = {attr = "jarvis_forge.__version__"}
35
+
36
+ [tool.setuptools.packages.find]
37
+ where = ["src"]
38
+
39
+ [tool.setuptools.package-data]
40
+ jarvis_forge = ["schemas/*.json", "examples/*.yaml", "recipes/*.yaml"]
41
+
42
+ [tool.pytest.ini_options]
43
+ testpaths = ["tests"]
44
+ pythonpath = ["src"]
45
+
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+