macrostates-cli 0.3.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 (31) hide show
  1. macrostates_cli-0.3.1/.macrostates/implementation/release.yaml +3 -0
  2. macrostates_cli-0.3.1/LICENSE +21 -0
  3. macrostates_cli-0.3.1/MANIFEST.in +1 -0
  4. macrostates_cli-0.3.1/PKG-INFO +259 -0
  5. macrostates_cli-0.3.1/README.md +244 -0
  6. macrostates_cli-0.3.1/pyproject.toml +60 -0
  7. macrostates_cli-0.3.1/setup.cfg +4 -0
  8. macrostates_cli-0.3.1/src/macrostates/__init__.py +23 -0
  9. macrostates_cli-0.3.1/src/macrostates/__main__.py +4 -0
  10. macrostates_cli-0.3.1/src/macrostates/_build_version.py +56 -0
  11. macrostates_cli-0.3.1/src/macrostates/_cli.py +158 -0
  12. macrostates_cli-0.3.1/src/macrostates/_formats/__init__.py +42 -0
  13. macrostates_cli-0.3.1/src/macrostates/_formats/common.py +102 -0
  14. macrostates_cli-0.3.1/src/macrostates/_formats/v0.py +11 -0
  15. macrostates_cli-0.3.1/src/macrostates/_formats/v1.py +44 -0
  16. macrostates_cli-0.3.1/src/macrostates/_integrity.py +144 -0
  17. macrostates_cli-0.3.1/src/macrostates/_io.py +118 -0
  18. macrostates_cli-0.3.1/src/macrostates/_models.py +71 -0
  19. macrostates_cli-0.3.1/src/macrostates/_mutations.py +53 -0
  20. macrostates_cli-0.3.1/src/macrostates/_project.py +527 -0
  21. macrostates_cli-0.3.1/src/macrostates/_scopes.py +34 -0
  22. macrostates_cli-0.3.1/src/macrostates/_sources.py +153 -0
  23. macrostates_cli-0.3.1/src/macrostates/_staged.py +56 -0
  24. macrostates_cli-0.3.1/src/macrostates/_validation.py +274 -0
  25. macrostates_cli-0.3.1/src/macrostates/py.typed +0 -0
  26. macrostates_cli-0.3.1/src/macrostates_cli.egg-info/PKG-INFO +259 -0
  27. macrostates_cli-0.3.1/src/macrostates_cli.egg-info/SOURCES.txt +29 -0
  28. macrostates_cli-0.3.1/src/macrostates_cli.egg-info/dependency_links.txt +1 -0
  29. macrostates_cli-0.3.1/src/macrostates_cli.egg-info/entry_points.txt +2 -0
  30. macrostates_cli-0.3.1/src/macrostates_cli.egg-info/requires.txt +1 -0
  31. macrostates_cli-0.3.1/src/macrostates_cli.egg-info/top_level.txt +1 -0
@@ -0,0 +1,3 @@
1
+ version: "0.3.1"
2
+ specification: "spec-0.3.0"
3
+ release_date: "2026-10-09"
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Lucas Lopez
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 @@
1
+ include .macrostates/implementation/release.yaml
@@ -0,0 +1,259 @@
1
+ Metadata-Version: 2.4
2
+ Name: macrostates-cli
3
+ Version: 0.3.1
4
+ Summary: Compose, install and validate versioned Macrostates specification packages.
5
+ Author-email: Lucas Lopez <713375+lucaslopez@users.noreply.github.com>
6
+ License-Expression: MIT
7
+ Project-URL: Repository, https://github.com/Macrostates/macrostates-cli
8
+ Project-URL: Documentation, https://github.com/Macrostates/macrostates-cli#readme
9
+ Project-URL: Issues, https://github.com/Macrostates/macrostates-cli/issues
10
+ Requires-Python: >=3.12
11
+ Description-Content-Type: text/markdown
12
+ License-File: LICENSE
13
+ Requires-Dist: PyYAML<7,>=6.0.2
14
+ Dynamic: license-file
15
+
16
+ # Macrostates CLI
17
+
18
+ Install, inspect and check reusable specification packages. Packages stay in
19
+ numbered, version-controlled directories such as `000_meta/` and `001_process/`.
20
+ The `macrostates` command and the `macrostates` Python API share the same core.
21
+
22
+ Requires Python 3.12 or newer. Distribution name: `macrostates-cli`.
23
+ Import package and executable name: `macrostates`. Version 0.3.1 is an initial
24
+ API; compatibility changes will be documented. Licensed under [MIT](https://github.com/Macrostates/macrostates-cli/blob/main/LICENSE).
25
+
26
+ ## Installation
27
+
28
+ Install from [PyPI](https://pypi.org/project/macrostates-cli/) with pip in a
29
+ Python 3.12 or newer environment:
30
+
31
+ ```bash
32
+ python -m pip install macrostates-cli
33
+ macrostates --help
34
+ ```
35
+
36
+ Use `python -m pip install macrostates-cli==0.3.1` for a fixed version, or
37
+ `python -m pip install --upgrade macrostates-cli` to update it. If your Python
38
+ installation requires a virtual environment, create one with
39
+ `python -m venv .venv` and activate it before installing.
40
+
41
+ For a command available outside a project environment, use
42
+ `pipx install macrostates-cli` or `uv tool install macrostates-cli`. Contributors
43
+ can clone the repository and run `uv sync --locked` as described below.
44
+
45
+ ## Start a project
46
+
47
+ Supply a composition whose package versions, authority and reading orders you
48
+ have selected. [The minimal composition](https://github.com/Macrostates/macrostates-cli/blob/main/examples/composition.yaml) selects only
49
+ Meta; add Process and the technology packages appropriate to your project.
50
+
51
+ ```bash
52
+ macrostates init --from /path/to/composition.yaml
53
+ macrostates install
54
+ macrostates info
55
+ macrostates check
56
+ ```
57
+
58
+ For a short setup, `macrostates init --name my-project --package meta@2.1.0`
59
+ creates a composition. Repeat `--package NAME@VERSION` for additional packages.
60
+ This shorthand uses the order you supplied for both reading and authority
61
+ (highest first); review those orders before installation. It does not select
62
+ dependencies automatically or replace versions with the latest releases.
63
+ Use `--from` for custom sources or deliberate orders.
64
+
65
+ The default layout is:
66
+
67
+ ```text
68
+ AGENTS.md
69
+ .macrostates/
70
+ specs/
71
+ main.md
72
+ composition.yaml
73
+ composition.lock.yaml
74
+ 000_meta/
75
+ ...
76
+ implementation/
77
+ main.md
78
+ ```
79
+
80
+ Commit the manifest, lockfile, package directories and project specifications.
81
+ Initialization preserves existing agent instructions and refuses to overwrite
82
+ project files. It prepares specification files; it does not implement an app.
83
+ Meta 2.0/2.1 and Process 3.0/4.0/4.1 define this layout. Their numbered packages and locks
84
+ remain tracked in Git. The CLI is strongly recommended and optional; reading
85
+ specifications and manual checks remain necessary for requirements beyond its
86
+ coverage. Existing projects keep their selected policies until explicitly migrated.
87
+
88
+ ## Commands
89
+
90
+ | Command | Purpose | Network / writes |
91
+ | --- | --- | --- |
92
+ | `init` | Prepare selected specification files | Local writes |
93
+ | `install` | Download and validate selected archive releases | Network and package/lock writes |
94
+ | `install --locked` | Restore an unchanged, locked selection | Network and package/lock writes |
95
+ | `lock` | Compare existing copies with canonical releases, then record integrity | Network and lock write |
96
+ | `verify` | Detect modified, missing or additional package files and executable changes | Offline, read-only |
97
+ | `lint` | Check metadata, dependencies, cycles, entrypoints, orders and local links | Offline, read-only |
98
+ | `info` | Display packages, provenance and dependency/order information | Offline, read-only |
99
+ | `check` | Combine lint and verify | Offline, read-only |
100
+ | `check --staged` | Check the Git index, including partially staged edits | Offline, read-only |
101
+
102
+ All commands accept `--project PATH` and `--json` before or after the command.
103
+ Project discovery selects the nearest composition and stops at the Git root.
104
+ It rejects competing `.yaml`/`.yml` manifests and ambiguous legacy/modern layouts.
105
+ Exit codes: **0** success, **1** failed checks, **2** invalid input/operation.
106
+ Argparse usage errors use its standard text output and exit code 2.
107
+
108
+ Local packages use `source: {type: local}` and are freely editable. Their metadata
109
+ and links are linted; they are excluded from downloaded-package integrity checks.
110
+ Every external package needs a real source to establish a lock. `lock` never
111
+ accepts local modifications as the baseline: it compares against the release.
112
+
113
+ ### Updating and recovering
114
+
115
+ Updates are deliberate manifest edits: change the
116
+ selected `version` and `source.tag` together, update the human entrypoint, then
117
+ run `install`. It replaces an old package only if its files still match its
118
+ previous locked inventory. Modified packages are left intact. A missing package
119
+ directory can be restored with `install --locked`.
120
+
121
+ Locks record full commit IDs and SHA-256 hashes of extracted file contents and
122
+ executable flags. ZIP/tar compression is not part of identity. Reinstallation
123
+ checks that the tag still selects its locked commit and fails if the tag moved.
124
+ The lock is a reviewable integrity baseline, not a digital signature: review its
125
+ changes together with package changes. `verify` is offline and cannot determine
126
+ whether a tag moved remotely.
127
+
128
+ Package operations validate all downloads and dependencies before replacing
129
+ files and roll back ordinary filesystem failures. A simultaneous CLI operation
130
+ is refused. An unexpected process termination may leave `.macrostates-operation`
131
+ and a `.macrostates-install-*` recovery directory; inspect those before removing
132
+ the marker or attempting recovery. Power-loss/crash-atomic filesystem commits
133
+ are not promised.
134
+
135
+ ### Private packages
136
+
137
+ The downloader accepts credential-free GitHub HTTPS or SSH repository URLs.
138
+ It uses an explicit Python API token, then `GH_TOKEN`/`GITHUB_TOKEN`, then an
139
+ existing GitHub CLI login. Tokens are never stored in composition or lockfiles.
140
+ Initialization and offline commands do not look up credentials. Package imports
141
+ do not execute downloaded code.
142
+
143
+ ### Checks before commits
144
+
145
+ Add the following entry to an existing pre-commit configuration after arranging
146
+ installation of the selected CLI version:
147
+
148
+ ```yaml
149
+ repos:
150
+ - repo: local
151
+ hooks:
152
+ - id: macrostates
153
+ name: Check staged Macrostates specifications
154
+ entry: macrostates check --staged
155
+ language: system
156
+ pass_filenames: false
157
+ always_run: true
158
+ ```
159
+
160
+ Run `macrostates check` in CI too. The CLI does not install hooks or change Git
161
+ settings automatically. Staged snapshots currently have a 128 MiB size limit
162
+ and exclude submodule contents. Structural checks do not prove semantic
163
+ consistency or implementation conformance. The local Markdown link checker
164
+ checks file targets, skips fenced code, and does not validate heading anchors
165
+ or implement a complete Markdown parser.
166
+
167
+ ## Python API
168
+
169
+ ```python
170
+ from macrostates import Project
171
+
172
+ project = Project.open("/path/to/project")
173
+ print(project.info())
174
+ report = project.check()
175
+ for diagnostic in report.diagnostics:
176
+ print(diagnostic.code, diagnostic.message, diagnostic.path)
177
+ assert report.ok
178
+ ```
179
+
180
+ Supported root exports: `Project`, `Report`, `Diagnostic`, `MacrostatesError`,
181
+ `GitHubSource`, and `SourceProvider`. `Project.open` and `Project.initialize`
182
+ construct projects; `install`, `lock`, `verify`, `lint`, `check`, and `info` are
183
+ the supported operations. `initialize` accepts a composition dictionary/path
184
+ or a `name` plus ordered `(package_name, version)` selections and a `layout`
185
+ of `modern` or `legacy`. Pass `source=GitHubSource(token=...)` for explicit
186
+ authentication or a `SourceProvider` implementation for another test transport.
187
+ `install(locked=True)` requires unchanged locked selections; `check(staged=True)`
188
+ checks the index. Expected configuration/operation errors raise
189
+ `MacrostatesError`; check failures are returned in `Report.diagnostics`.
190
+ Ordinary file read failures can raise `OSError`. Imports perform no project-local
191
+ or network I/O and do not configure logging. Accessing `__version__` explicitly
192
+ reads installed distribution metadata; it does not read a project declaration. The CLI configures standard logging when explicitly invoked.
193
+
194
+ ## Compatibility and development
195
+
196
+ Unversioned compositions use the retained legacy reader. New compositions use
197
+ `schema_version: 1`. Both legacy `specs/` and `.macrostates/specs/` layouts are
198
+ recognized. Existing `git-subtree` compositions can be inspected, linted and
199
+ given an upstream-verified integrity lock without changing subtree history.
200
+ Archive `install` refuses subtree sources; use Git subtree maintenance until an
201
+ explicit migration is requested. Old branch-only/commit selectors need explicit
202
+ tag migration and are reported instead of being silently reinterpreted.
203
+
204
+ Package release versions are independent of format versions. Existing package
205
+ metadata is format 1, as is an explicit `schema_version: 1`. Unknown manifest,
206
+ metadata or lock formats fail clearly. Release policy adapters support Meta
207
+ 2.0.x/2.1.x and Process 2.3.x/2.4.x/3.0.x/4.0.x/4.1.x. Modern policies require the modern
208
+ layout; Meta 2 also requires composition format 1. Earlier Meta releases and
209
+ Process 1.x/2.0–2.2 retain their existing checks. Future policy releases receive
210
+ explicit unsupported diagnostics rather than guessed requirements. Process 4's
211
+ feature-branch and PR rules require manual workflow review; CLI checks do not
212
+ verify branch discipline or authorize Git operations.
213
+
214
+ `info` lists directory-scoped specifications under visible component directories;
215
+ `lint` checks their local file links. The scope root is the component containing
216
+ `.macrostates/`. Separately composed subprojects are checked independently.
217
+ Tool/cache/build/temporary and hidden implementation directories are excluded
218
+ from this discovery; inspect their applicable scopes manually. Scope authority,
219
+ semantic requirements and workflow conformance always need specification reading.
220
+ See [architecture](https://github.com/Macrostates/macrostates-cli/blob/main/.macrostates/implementation/main.md) for adapter extension guidance and
221
+ [project specifications](https://github.com/Macrostates/macrostates-cli/blob/main/.macrostates/specs/main.md) for this repository's working rules.
222
+ The [CLI specification package](https://github.com/Macrostates/macrostates-cli/blob/main/.macrostates/specs/051_cli/README.md) defines the
223
+ public library, commands, composition, integrity and versioning contracts;
224
+ [conformance evidence](https://github.com/Macrostates/macrostates-cli/blob/main/.macrostates/implementation/specification-conformance.md)
225
+ maps those requirements to implementation and verification.
226
+
227
+ ```bash
228
+ uv sync --locked
229
+ uv run ruff check .
230
+ uv run ruff format --check .
231
+ uv run pyright
232
+ uv run pytest --cov=macrostates --cov-report=term-missing
233
+ uv build
234
+ ```
235
+
236
+ The contributor `uv.lock` is committed for repeatable development and CI.
237
+ Builds go to ignored `dist/`; temporary work goes to `tmp/<activity>/`.
238
+ Automated update planning, workflow commands, release publishing and migrations
239
+ are future features.
240
+
241
+ ## This repository's specifications and version
242
+
243
+ The CLI manages its own specification composition under `.macrostates/specs/`,
244
+ using Meta 2.1.0, Process 4.1.0, Repository 3.1.0, Python 2.1.0 and Python-library
245
+ 1.1.0 as canonical archive snapshots. Its local CLI requirements remain editable.
246
+ `macrostates check` and `check --staged` validate the same files contributors use.
247
+ This is also a real integration test of the supported package installation path.
248
+
249
+ The implementation's single version declaration is
250
+ [release.yaml](https://github.com/Macrostates/macrostates-cli/blob/main/.macrostates/implementation/release.yaml); the specification baseline
251
+ is `project.version` in the composition. Setuptools reads the declaration during
252
+ isolated builds. The sdist includes that one declaration, while the wheel reports
253
+ its installed distribution version. Builds do not edit declarations, create tags
254
+ or require Git/network access to obtain release metadata. Ordinary dependency
255
+ installation may still require access to package indexes.
256
+
257
+ ## AI assistance
258
+
259
+ This project was developed with AI assistance.
@@ -0,0 +1,244 @@
1
+ # Macrostates CLI
2
+
3
+ Install, inspect and check reusable specification packages. Packages stay in
4
+ numbered, version-controlled directories such as `000_meta/` and `001_process/`.
5
+ The `macrostates` command and the `macrostates` Python API share the same core.
6
+
7
+ Requires Python 3.12 or newer. Distribution name: `macrostates-cli`.
8
+ Import package and executable name: `macrostates`. Version 0.3.1 is an initial
9
+ API; compatibility changes will be documented. Licensed under [MIT](https://github.com/Macrostates/macrostates-cli/blob/main/LICENSE).
10
+
11
+ ## Installation
12
+
13
+ Install from [PyPI](https://pypi.org/project/macrostates-cli/) with pip in a
14
+ Python 3.12 or newer environment:
15
+
16
+ ```bash
17
+ python -m pip install macrostates-cli
18
+ macrostates --help
19
+ ```
20
+
21
+ Use `python -m pip install macrostates-cli==0.3.1` for a fixed version, or
22
+ `python -m pip install --upgrade macrostates-cli` to update it. If your Python
23
+ installation requires a virtual environment, create one with
24
+ `python -m venv .venv` and activate it before installing.
25
+
26
+ For a command available outside a project environment, use
27
+ `pipx install macrostates-cli` or `uv tool install macrostates-cli`. Contributors
28
+ can clone the repository and run `uv sync --locked` as described below.
29
+
30
+ ## Start a project
31
+
32
+ Supply a composition whose package versions, authority and reading orders you
33
+ have selected. [The minimal composition](https://github.com/Macrostates/macrostates-cli/blob/main/examples/composition.yaml) selects only
34
+ Meta; add Process and the technology packages appropriate to your project.
35
+
36
+ ```bash
37
+ macrostates init --from /path/to/composition.yaml
38
+ macrostates install
39
+ macrostates info
40
+ macrostates check
41
+ ```
42
+
43
+ For a short setup, `macrostates init --name my-project --package meta@2.1.0`
44
+ creates a composition. Repeat `--package NAME@VERSION` for additional packages.
45
+ This shorthand uses the order you supplied for both reading and authority
46
+ (highest first); review those orders before installation. It does not select
47
+ dependencies automatically or replace versions with the latest releases.
48
+ Use `--from` for custom sources or deliberate orders.
49
+
50
+ The default layout is:
51
+
52
+ ```text
53
+ AGENTS.md
54
+ .macrostates/
55
+ specs/
56
+ main.md
57
+ composition.yaml
58
+ composition.lock.yaml
59
+ 000_meta/
60
+ ...
61
+ implementation/
62
+ main.md
63
+ ```
64
+
65
+ Commit the manifest, lockfile, package directories and project specifications.
66
+ Initialization preserves existing agent instructions and refuses to overwrite
67
+ project files. It prepares specification files; it does not implement an app.
68
+ Meta 2.0/2.1 and Process 3.0/4.0/4.1 define this layout. Their numbered packages and locks
69
+ remain tracked in Git. The CLI is strongly recommended and optional; reading
70
+ specifications and manual checks remain necessary for requirements beyond its
71
+ coverage. Existing projects keep their selected policies until explicitly migrated.
72
+
73
+ ## Commands
74
+
75
+ | Command | Purpose | Network / writes |
76
+ | --- | --- | --- |
77
+ | `init` | Prepare selected specification files | Local writes |
78
+ | `install` | Download and validate selected archive releases | Network and package/lock writes |
79
+ | `install --locked` | Restore an unchanged, locked selection | Network and package/lock writes |
80
+ | `lock` | Compare existing copies with canonical releases, then record integrity | Network and lock write |
81
+ | `verify` | Detect modified, missing or additional package files and executable changes | Offline, read-only |
82
+ | `lint` | Check metadata, dependencies, cycles, entrypoints, orders and local links | Offline, read-only |
83
+ | `info` | Display packages, provenance and dependency/order information | Offline, read-only |
84
+ | `check` | Combine lint and verify | Offline, read-only |
85
+ | `check --staged` | Check the Git index, including partially staged edits | Offline, read-only |
86
+
87
+ All commands accept `--project PATH` and `--json` before or after the command.
88
+ Project discovery selects the nearest composition and stops at the Git root.
89
+ It rejects competing `.yaml`/`.yml` manifests and ambiguous legacy/modern layouts.
90
+ Exit codes: **0** success, **1** failed checks, **2** invalid input/operation.
91
+ Argparse usage errors use its standard text output and exit code 2.
92
+
93
+ Local packages use `source: {type: local}` and are freely editable. Their metadata
94
+ and links are linted; they are excluded from downloaded-package integrity checks.
95
+ Every external package needs a real source to establish a lock. `lock` never
96
+ accepts local modifications as the baseline: it compares against the release.
97
+
98
+ ### Updating and recovering
99
+
100
+ Updates are deliberate manifest edits: change the
101
+ selected `version` and `source.tag` together, update the human entrypoint, then
102
+ run `install`. It replaces an old package only if its files still match its
103
+ previous locked inventory. Modified packages are left intact. A missing package
104
+ directory can be restored with `install --locked`.
105
+
106
+ Locks record full commit IDs and SHA-256 hashes of extracted file contents and
107
+ executable flags. ZIP/tar compression is not part of identity. Reinstallation
108
+ checks that the tag still selects its locked commit and fails if the tag moved.
109
+ The lock is a reviewable integrity baseline, not a digital signature: review its
110
+ changes together with package changes. `verify` is offline and cannot determine
111
+ whether a tag moved remotely.
112
+
113
+ Package operations validate all downloads and dependencies before replacing
114
+ files and roll back ordinary filesystem failures. A simultaneous CLI operation
115
+ is refused. An unexpected process termination may leave `.macrostates-operation`
116
+ and a `.macrostates-install-*` recovery directory; inspect those before removing
117
+ the marker or attempting recovery. Power-loss/crash-atomic filesystem commits
118
+ are not promised.
119
+
120
+ ### Private packages
121
+
122
+ The downloader accepts credential-free GitHub HTTPS or SSH repository URLs.
123
+ It uses an explicit Python API token, then `GH_TOKEN`/`GITHUB_TOKEN`, then an
124
+ existing GitHub CLI login. Tokens are never stored in composition or lockfiles.
125
+ Initialization and offline commands do not look up credentials. Package imports
126
+ do not execute downloaded code.
127
+
128
+ ### Checks before commits
129
+
130
+ Add the following entry to an existing pre-commit configuration after arranging
131
+ installation of the selected CLI version:
132
+
133
+ ```yaml
134
+ repos:
135
+ - repo: local
136
+ hooks:
137
+ - id: macrostates
138
+ name: Check staged Macrostates specifications
139
+ entry: macrostates check --staged
140
+ language: system
141
+ pass_filenames: false
142
+ always_run: true
143
+ ```
144
+
145
+ Run `macrostates check` in CI too. The CLI does not install hooks or change Git
146
+ settings automatically. Staged snapshots currently have a 128 MiB size limit
147
+ and exclude submodule contents. Structural checks do not prove semantic
148
+ consistency or implementation conformance. The local Markdown link checker
149
+ checks file targets, skips fenced code, and does not validate heading anchors
150
+ or implement a complete Markdown parser.
151
+
152
+ ## Python API
153
+
154
+ ```python
155
+ from macrostates import Project
156
+
157
+ project = Project.open("/path/to/project")
158
+ print(project.info())
159
+ report = project.check()
160
+ for diagnostic in report.diagnostics:
161
+ print(diagnostic.code, diagnostic.message, diagnostic.path)
162
+ assert report.ok
163
+ ```
164
+
165
+ Supported root exports: `Project`, `Report`, `Diagnostic`, `MacrostatesError`,
166
+ `GitHubSource`, and `SourceProvider`. `Project.open` and `Project.initialize`
167
+ construct projects; `install`, `lock`, `verify`, `lint`, `check`, and `info` are
168
+ the supported operations. `initialize` accepts a composition dictionary/path
169
+ or a `name` plus ordered `(package_name, version)` selections and a `layout`
170
+ of `modern` or `legacy`. Pass `source=GitHubSource(token=...)` for explicit
171
+ authentication or a `SourceProvider` implementation for another test transport.
172
+ `install(locked=True)` requires unchanged locked selections; `check(staged=True)`
173
+ checks the index. Expected configuration/operation errors raise
174
+ `MacrostatesError`; check failures are returned in `Report.diagnostics`.
175
+ Ordinary file read failures can raise `OSError`. Imports perform no project-local
176
+ or network I/O and do not configure logging. Accessing `__version__` explicitly
177
+ reads installed distribution metadata; it does not read a project declaration. The CLI configures standard logging when explicitly invoked.
178
+
179
+ ## Compatibility and development
180
+
181
+ Unversioned compositions use the retained legacy reader. New compositions use
182
+ `schema_version: 1`. Both legacy `specs/` and `.macrostates/specs/` layouts are
183
+ recognized. Existing `git-subtree` compositions can be inspected, linted and
184
+ given an upstream-verified integrity lock without changing subtree history.
185
+ Archive `install` refuses subtree sources; use Git subtree maintenance until an
186
+ explicit migration is requested. Old branch-only/commit selectors need explicit
187
+ tag migration and are reported instead of being silently reinterpreted.
188
+
189
+ Package release versions are independent of format versions. Existing package
190
+ metadata is format 1, as is an explicit `schema_version: 1`. Unknown manifest,
191
+ metadata or lock formats fail clearly. Release policy adapters support Meta
192
+ 2.0.x/2.1.x and Process 2.3.x/2.4.x/3.0.x/4.0.x/4.1.x. Modern policies require the modern
193
+ layout; Meta 2 also requires composition format 1. Earlier Meta releases and
194
+ Process 1.x/2.0–2.2 retain their existing checks. Future policy releases receive
195
+ explicit unsupported diagnostics rather than guessed requirements. Process 4's
196
+ feature-branch and PR rules require manual workflow review; CLI checks do not
197
+ verify branch discipline or authorize Git operations.
198
+
199
+ `info` lists directory-scoped specifications under visible component directories;
200
+ `lint` checks their local file links. The scope root is the component containing
201
+ `.macrostates/`. Separately composed subprojects are checked independently.
202
+ Tool/cache/build/temporary and hidden implementation directories are excluded
203
+ from this discovery; inspect their applicable scopes manually. Scope authority,
204
+ semantic requirements and workflow conformance always need specification reading.
205
+ See [architecture](https://github.com/Macrostates/macrostates-cli/blob/main/.macrostates/implementation/main.md) for adapter extension guidance and
206
+ [project specifications](https://github.com/Macrostates/macrostates-cli/blob/main/.macrostates/specs/main.md) for this repository's working rules.
207
+ The [CLI specification package](https://github.com/Macrostates/macrostates-cli/blob/main/.macrostates/specs/051_cli/README.md) defines the
208
+ public library, commands, composition, integrity and versioning contracts;
209
+ [conformance evidence](https://github.com/Macrostates/macrostates-cli/blob/main/.macrostates/implementation/specification-conformance.md)
210
+ maps those requirements to implementation and verification.
211
+
212
+ ```bash
213
+ uv sync --locked
214
+ uv run ruff check .
215
+ uv run ruff format --check .
216
+ uv run pyright
217
+ uv run pytest --cov=macrostates --cov-report=term-missing
218
+ uv build
219
+ ```
220
+
221
+ The contributor `uv.lock` is committed for repeatable development and CI.
222
+ Builds go to ignored `dist/`; temporary work goes to `tmp/<activity>/`.
223
+ Automated update planning, workflow commands, release publishing and migrations
224
+ are future features.
225
+
226
+ ## This repository's specifications and version
227
+
228
+ The CLI manages its own specification composition under `.macrostates/specs/`,
229
+ using Meta 2.1.0, Process 4.1.0, Repository 3.1.0, Python 2.1.0 and Python-library
230
+ 1.1.0 as canonical archive snapshots. Its local CLI requirements remain editable.
231
+ `macrostates check` and `check --staged` validate the same files contributors use.
232
+ This is also a real integration test of the supported package installation path.
233
+
234
+ The implementation's single version declaration is
235
+ [release.yaml](https://github.com/Macrostates/macrostates-cli/blob/main/.macrostates/implementation/release.yaml); the specification baseline
236
+ is `project.version` in the composition. Setuptools reads the declaration during
237
+ isolated builds. The sdist includes that one declaration, while the wheel reports
238
+ its installed distribution version. Builds do not edit declarations, create tags
239
+ or require Git/network access to obtain release metadata. Ordinary dependency
240
+ installation may still require access to package indexes.
241
+
242
+ ## AI assistance
243
+
244
+ This project was developed with AI assistance.
@@ -0,0 +1,60 @@
1
+ [build-system]
2
+ requires = ["setuptools>=77", "PyYAML>=6.0.2,<7"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "macrostates-cli"
7
+ dynamic = ["version"]
8
+ description = "Compose, install and validate versioned Macrostates specification packages."
9
+ readme = "README.md"
10
+ requires-python = ">=3.12"
11
+ license = "MIT"
12
+ license-files = ["LICENSE"]
13
+ authors = [{name = "Lucas Lopez", email = "713375+lucaslopez@users.noreply.github.com"}]
14
+ dependencies = ["PyYAML>=6.0.2,<7"]
15
+
16
+ [project.urls]
17
+ Repository = "https://github.com/Macrostates/macrostates-cli"
18
+ Documentation = "https://github.com/Macrostates/macrostates-cli#readme"
19
+ Issues = "https://github.com/Macrostates/macrostates-cli/issues"
20
+
21
+ [project.scripts]
22
+ macrostates = "macrostates._cli:main"
23
+
24
+ [dependency-groups]
25
+ dev = ["pytest>=8", "pytest-cov>=6", "ruff>=0.9", "pyright>=1.1.390", "types-PyYAML>=6"]
26
+
27
+ [tool.uv]
28
+ cache-keys = [
29
+ {file = "pyproject.toml"},
30
+ {file = ".macrostates/implementation/release.yaml"},
31
+ {file = "README.md"},
32
+ {dir = "src"},
33
+ ]
34
+
35
+ [tool.setuptools.packages.find]
36
+ where = ["src"]
37
+
38
+ [tool.setuptools.package-data]
39
+ macrostates = ["py.typed"]
40
+
41
+ [tool.setuptools.dynamic]
42
+ version = {attr = "macrostates._build_version.VERSION"}
43
+
44
+ [tool.pytest.ini_options]
45
+ testpaths = ["tests"]
46
+ addopts = "--strict-markers"
47
+
48
+ [tool.ruff]
49
+ target-version = "py312"
50
+ line-length = 100
51
+
52
+ [tool.ruff.lint]
53
+ select = ["E4", "E7", "E9", "F", "I", "UP", "B"]
54
+
55
+ [tool.pyright]
56
+ include = ["src", "examples"]
57
+ pythonVersion = "3.12"
58
+ typeCheckingMode = "standard"
59
+ venvPath = "."
60
+ venv = ".venv"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,23 @@
1
+ """The public API. Imports perform no network or project-local file access."""
2
+
3
+ from importlib.metadata import PackageNotFoundError, version
4
+
5
+ from ._models import Diagnostic, MacrostatesError, Report
6
+ from ._project import Project
7
+ from ._sources import GitHubSource, SourceProvider
8
+
9
+ __all__ = ["Diagnostic", "GitHubSource", "MacrostatesError", "Project", "Report", "SourceProvider"]
10
+
11
+
12
+ def __getattr__(name: str) -> str:
13
+ if name != "__version__":
14
+ raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
15
+ # Read distribution metadata only when a caller explicitly requests a version.
16
+ try:
17
+ return version("macrostates-cli")
18
+ except PackageNotFoundError:
19
+ return "0+uninstalled"
20
+
21
+
22
+ def __dir__() -> list[str]:
23
+ return sorted([*globals(), "__version__"])
@@ -0,0 +1,4 @@
1
+ from ._cli import main
2
+
3
+ if __name__ == "__main__":
4
+ raise SystemExit(main())