pyodcs 0.2.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.
- pyodcs-0.2.0/.editorconfig +18 -0
- pyodcs-0.2.0/.github/workflows/checks.yml +47 -0
- pyodcs-0.2.0/.github/workflows/ci.yml +9 -0
- pyodcs-0.2.0/.github/workflows/release.yml +217 -0
- pyodcs-0.2.0/.gitignore +28 -0
- pyodcs-0.2.0/CHANGELOG.md +24 -0
- pyodcs-0.2.0/CONTRIBUTING.md +48 -0
- pyodcs-0.2.0/Cargo.lock +647 -0
- pyodcs-0.2.0/Cargo.toml +49 -0
- pyodcs-0.2.0/LICENSE +17 -0
- pyodcs-0.2.0/PKG-INFO +119 -0
- pyodcs-0.2.0/README.md +94 -0
- pyodcs-0.2.0/ROADMAP.md +120 -0
- pyodcs-0.2.0/SPEC.md +173 -0
- pyodcs-0.2.0/docs/README.md +30 -0
- pyodcs-0.2.0/docs/implementation/README.md +26 -0
- pyodcs-0.2.0/docs/implementation/architecture.md +25 -0
- pyodcs-0.2.0/docs/implementation/cli-spec.md +31 -0
- pyodcs-0.2.0/docs/implementation/crate-layout.md +74 -0
- pyodcs-0.2.0/docs/implementation/diagnostics-guide.md +32 -0
- pyodcs-0.2.0/docs/implementation/implementation-phases.md +78 -0
- pyodcs-0.2.0/docs/implementation/model-guide.md +36 -0
- pyodcs-0.2.0/docs/implementation/non-goals.md +14 -0
- pyodcs-0.2.0/docs/implementation/project-goal.md +29 -0
- pyodcs-0.2.0/docs/implementation/public-api.md +23 -0
- pyodcs-0.2.0/docs/implementation/relationship-to-dtcs.md +29 -0
- pyodcs-0.2.0/docs/implementation/rust-dependencies.md +23 -0
- pyodcs-0.2.0/docs/implementation/spec-usage.md +15 -0
- pyodcs-0.2.0/docs/implementation/testing-plan.md +18 -0
- pyodcs-0.2.0/docs/implementation/validation-guide.md +17 -0
- pyodcs-0.2.0/examples/minimal.odcs.json +33 -0
- pyodcs-0.2.0/examples/minimal.odcs.yaml +22 -0
- pyodcs-0.2.0/pyproject.toml +40 -0
- pyodcs-0.2.0/python/pyodcs/__init__.py +75 -0
- pyodcs-0.2.0/python/pyodcs/__main__.py +137 -0
- pyodcs-0.2.0/python/tests/test_pyodcs.py +54 -0
- pyodcs-0.2.0/src/bin/odcs.rs +11 -0
- pyodcs-0.2.0/src/cli/mod.rs +279 -0
- pyodcs-0.2.0/src/compatibility/mod.rs +3 -0
- pyodcs-0.2.0/src/diagnostics/builders.rs +36 -0
- pyodcs-0.2.0/src/diagnostics/category.rs +25 -0
- pyodcs-0.2.0/src/diagnostics/codes.rs +20 -0
- pyodcs-0.2.0/src/diagnostics/diagnostic.rs +71 -0
- pyodcs-0.2.0/src/diagnostics/mod.rs +33 -0
- pyodcs-0.2.0/src/diagnostics/report.rs +52 -0
- pyodcs-0.2.0/src/diagnostics/severity.rs +23 -0
- pyodcs-0.2.0/src/diagnostics/stage.rs +21 -0
- pyodcs-0.2.0/src/lib.rs +73 -0
- pyodcs-0.2.0/src/model/contract.rs +41 -0
- pyodcs-0.2.0/src/model/custom.rs +3 -0
- pyodcs-0.2.0/src/model/field.rs +20 -0
- pyodcs-0.2.0/src/model/fundamentals.rs +3 -0
- pyodcs-0.2.0/src/model/mod.rs +21 -0
- pyodcs-0.2.0/src/model/pricing.rs +3 -0
- pyodcs-0.2.0/src/model/quality.rs +20 -0
- pyodcs-0.2.0/src/model/roles.rs +3 -0
- pyodcs-0.2.0/src/model/schema.rs +19 -0
- pyodcs-0.2.0/src/model/servers.rs +3 -0
- pyodcs-0.2.0/src/model/sla.rs +3 -0
- pyodcs-0.2.0/src/model/stakeholders.rs +3 -0
- pyodcs-0.2.0/src/model/support.rs +3 -0
- pyodcs-0.2.0/src/model/team.rs +3 -0
- pyodcs-0.2.0/src/model/versioning.rs +3 -0
- pyodcs-0.2.0/src/parser/json.rs +35 -0
- pyodcs-0.2.0/src/parser/mod.rs +86 -0
- pyodcs-0.2.0/src/parser/yaml.rs +35 -0
- pyodcs-0.2.0/src/python.rs +128 -0
- pyodcs-0.2.0/src/registry/mod.rs +3 -0
- pyodcs-0.2.0/src/validation/document.rs +13 -0
- pyodcs-0.2.0/src/validation/extensions.rs +13 -0
- pyodcs-0.2.0/src/validation/mod.rs +65 -0
- pyodcs-0.2.0/src/validation/phases.rs +20 -0
- pyodcs-0.2.0/src/validation/quality.rs +13 -0
- pyodcs-0.2.0/src/validation/references.rs +13 -0
- pyodcs-0.2.0/src/validation/schema.rs +13 -0
- pyodcs-0.2.0/src/validation/structural.rs +13 -0
- pyodcs-0.2.0/tests/cli.rs +99 -0
- pyodcs-0.2.0/tests/fixtures/invalid-empty-name.yaml +4 -0
- pyodcs-0.2.0/tests/fixtures/invalid-kind.yaml +4 -0
- pyodcs-0.2.0/tests/fixtures/malformed.json +1 -0
- pyodcs-0.2.0/tests/fixtures/malformed.yaml +1 -0
- pyodcs-0.2.0/tests/fixtures/minimal.odcs.json +33 -0
- pyodcs-0.2.0/tests/fixtures/minimal.odcs.yaml +22 -0
- pyodcs-0.2.0/tests/fixtures/unsupported-version.yaml +4 -0
- pyodcs-0.2.0/tests/fixtures/with-extensions.yaml +7 -0
- pyodcs-0.2.0/tests/skeleton.rs +141 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
root = true
|
|
2
|
+
|
|
3
|
+
[*]
|
|
4
|
+
charset = utf-8
|
|
5
|
+
end_of_line = lf
|
|
6
|
+
insert_final_newline = true
|
|
7
|
+
trim_trailing_whitespace = true
|
|
8
|
+
|
|
9
|
+
[*.md]
|
|
10
|
+
trim_trailing_whitespace = false
|
|
11
|
+
|
|
12
|
+
[*.{rs,toml}]
|
|
13
|
+
indent_style = space
|
|
14
|
+
indent_size = 4
|
|
15
|
+
|
|
16
|
+
[*.yaml]
|
|
17
|
+
indent_style = space
|
|
18
|
+
indent_size = 2
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
name: Checks
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_call:
|
|
5
|
+
|
|
6
|
+
env:
|
|
7
|
+
CARGO_TERM_COLOR: always
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
python:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
steps:
|
|
13
|
+
- uses: actions/checkout@v4
|
|
14
|
+
- uses: dtolnay/rust-toolchain@stable
|
|
15
|
+
- uses: actions/setup-python@v5
|
|
16
|
+
with:
|
|
17
|
+
python-version: "3.12"
|
|
18
|
+
- name: Build and test Python package
|
|
19
|
+
run: |
|
|
20
|
+
python -m venv .venv
|
|
21
|
+
source .venv/bin/activate
|
|
22
|
+
python -m pip install --upgrade pip
|
|
23
|
+
python -m pip install maturin pytest
|
|
24
|
+
maturin develop --features python --locked
|
|
25
|
+
pytest python/tests -v
|
|
26
|
+
- name: maturin build (dry run)
|
|
27
|
+
run: |
|
|
28
|
+
source .venv/bin/activate
|
|
29
|
+
maturin build --features python --locked
|
|
30
|
+
|
|
31
|
+
rust:
|
|
32
|
+
runs-on: ubuntu-latest
|
|
33
|
+
steps:
|
|
34
|
+
- uses: actions/checkout@v4
|
|
35
|
+
- uses: dtolnay/rust-toolchain@stable
|
|
36
|
+
with:
|
|
37
|
+
components: rustfmt, clippy
|
|
38
|
+
- name: cargo fmt
|
|
39
|
+
run: cargo fmt --all -- --check
|
|
40
|
+
- name: cargo clippy
|
|
41
|
+
run: cargo clippy --all-targets -- -D warnings
|
|
42
|
+
- name: cargo test
|
|
43
|
+
run: cargo test --locked
|
|
44
|
+
- name: cargo build
|
|
45
|
+
run: cargo build --locked --all-targets
|
|
46
|
+
- name: cargo publish (dry run)
|
|
47
|
+
run: cargo publish --dry-run --locked
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*.*.*"
|
|
7
|
+
|
|
8
|
+
env:
|
|
9
|
+
CARGO_TERM_COLOR: always
|
|
10
|
+
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
|
|
11
|
+
MATURIN_PYPI_TOKEN: ${{ secrets.PYPI_API_TOKEN }}
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
checks:
|
|
15
|
+
uses: ./.github/workflows/checks.yml
|
|
16
|
+
|
|
17
|
+
publish-crates-io:
|
|
18
|
+
needs: checks
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
steps:
|
|
21
|
+
- uses: actions/checkout@v4
|
|
22
|
+
- uses: dtolnay/rust-toolchain@stable
|
|
23
|
+
- name: Verify tag matches crate and Python versions
|
|
24
|
+
run: |
|
|
25
|
+
crate_version=$(grep '^version' Cargo.toml | head -1 | cut -d'"' -f2)
|
|
26
|
+
py_version=$(grep '^version' pyproject.toml | head -1 | cut -d'"' -f2)
|
|
27
|
+
tag_version="${GITHUB_REF_NAME#v}"
|
|
28
|
+
if [ "$crate_version" != "$tag_version" ]; then
|
|
29
|
+
echo "Tag ${GITHUB_REF_NAME} (v${tag_version}) does not match Cargo.toml version ${crate_version}"
|
|
30
|
+
exit 1
|
|
31
|
+
fi
|
|
32
|
+
if [ "$py_version" != "$tag_version" ]; then
|
|
33
|
+
echo "Tag ${GITHUB_REF_NAME} (v${tag_version}) does not match pyproject.toml version ${py_version}"
|
|
34
|
+
exit 1
|
|
35
|
+
fi
|
|
36
|
+
- name: cargo publish
|
|
37
|
+
run: |
|
|
38
|
+
set +e
|
|
39
|
+
output="$(cargo publish --locked --token "$CARGO_REGISTRY_TOKEN" 2>&1)"
|
|
40
|
+
code=$?
|
|
41
|
+
echo "$output"
|
|
42
|
+
if [ "$code" -ne 0 ] && echo "$output" | grep -q "already exists on crates.io index"; then
|
|
43
|
+
echo "crate already published; skipping"
|
|
44
|
+
exit 0
|
|
45
|
+
fi
|
|
46
|
+
exit "$code"
|
|
47
|
+
|
|
48
|
+
build-python-linux:
|
|
49
|
+
needs: checks
|
|
50
|
+
runs-on: ${{ matrix.platform.runner }}
|
|
51
|
+
strategy:
|
|
52
|
+
fail-fast: false
|
|
53
|
+
matrix:
|
|
54
|
+
platform:
|
|
55
|
+
- runner: ubuntu-22.04
|
|
56
|
+
target: x86_64
|
|
57
|
+
- runner: ubuntu-22.04
|
|
58
|
+
target: x86
|
|
59
|
+
- runner: ubuntu-22.04
|
|
60
|
+
target: aarch64
|
|
61
|
+
manylinux: 2_28
|
|
62
|
+
- runner: ubuntu-22.04
|
|
63
|
+
target: armv7
|
|
64
|
+
- runner: ubuntu-22.04
|
|
65
|
+
target: s390x
|
|
66
|
+
- runner: ubuntu-22.04
|
|
67
|
+
target: ppc64le
|
|
68
|
+
steps:
|
|
69
|
+
- uses: actions/checkout@v4
|
|
70
|
+
- uses: actions/setup-python@v5
|
|
71
|
+
with:
|
|
72
|
+
python-version: "3.12"
|
|
73
|
+
- name: Build wheels
|
|
74
|
+
uses: PyO3/maturin-action@v1
|
|
75
|
+
with:
|
|
76
|
+
target: ${{ matrix.platform.target }}
|
|
77
|
+
args: --release --out dist --features python --locked --compatibility pypi
|
|
78
|
+
sccache: "true"
|
|
79
|
+
manylinux: ${{ matrix.platform.manylinux || 'auto' }}
|
|
80
|
+
- uses: actions/upload-artifact@v4
|
|
81
|
+
with:
|
|
82
|
+
name: python-dist-linux-${{ matrix.platform.target }}
|
|
83
|
+
path: dist/*
|
|
84
|
+
if-no-files-found: error
|
|
85
|
+
|
|
86
|
+
build-python-musllinux:
|
|
87
|
+
needs: checks
|
|
88
|
+
runs-on: ${{ matrix.platform.runner }}
|
|
89
|
+
strategy:
|
|
90
|
+
fail-fast: false
|
|
91
|
+
matrix:
|
|
92
|
+
platform:
|
|
93
|
+
- runner: ubuntu-22.04
|
|
94
|
+
target: x86_64
|
|
95
|
+
- runner: ubuntu-22.04
|
|
96
|
+
target: x86
|
|
97
|
+
- runner: ubuntu-22.04
|
|
98
|
+
target: aarch64
|
|
99
|
+
- runner: ubuntu-22.04
|
|
100
|
+
target: armv7
|
|
101
|
+
steps:
|
|
102
|
+
- uses: actions/checkout@v4
|
|
103
|
+
- uses: actions/setup-python@v5
|
|
104
|
+
with:
|
|
105
|
+
python-version: "3.12"
|
|
106
|
+
- name: Build wheels
|
|
107
|
+
uses: PyO3/maturin-action@v1
|
|
108
|
+
with:
|
|
109
|
+
target: ${{ matrix.platform.target }}
|
|
110
|
+
args: --release --out dist --features python --locked --compatibility pypi
|
|
111
|
+
sccache: "true"
|
|
112
|
+
manylinux: musllinux_1_2
|
|
113
|
+
- uses: actions/upload-artifact@v4
|
|
114
|
+
with:
|
|
115
|
+
name: python-dist-musllinux-${{ matrix.platform.target }}
|
|
116
|
+
path: dist/*
|
|
117
|
+
if-no-files-found: error
|
|
118
|
+
|
|
119
|
+
build-python-windows:
|
|
120
|
+
needs: checks
|
|
121
|
+
runs-on: ${{ matrix.platform.runner }}
|
|
122
|
+
strategy:
|
|
123
|
+
fail-fast: false
|
|
124
|
+
matrix:
|
|
125
|
+
platform:
|
|
126
|
+
- runner: windows-latest
|
|
127
|
+
target: x64
|
|
128
|
+
python_arch: x64
|
|
129
|
+
- runner: windows-latest
|
|
130
|
+
target: x86
|
|
131
|
+
python_arch: x86
|
|
132
|
+
- runner: windows-11-arm
|
|
133
|
+
target: aarch64
|
|
134
|
+
python_arch: arm64
|
|
135
|
+
steps:
|
|
136
|
+
- uses: actions/checkout@v4
|
|
137
|
+
- uses: actions/setup-python@v5
|
|
138
|
+
with:
|
|
139
|
+
python-version: "3.12"
|
|
140
|
+
architecture: ${{ matrix.platform.python_arch }}
|
|
141
|
+
- name: Build wheels
|
|
142
|
+
uses: PyO3/maturin-action@v1
|
|
143
|
+
with:
|
|
144
|
+
target: ${{ matrix.platform.target }}
|
|
145
|
+
args: --release --out dist --features python --locked --compatibility pypi
|
|
146
|
+
sccache: "true"
|
|
147
|
+
- uses: actions/upload-artifact@v4
|
|
148
|
+
with:
|
|
149
|
+
name: python-dist-windows-${{ matrix.platform.target }}
|
|
150
|
+
path: dist/*
|
|
151
|
+
if-no-files-found: error
|
|
152
|
+
|
|
153
|
+
build-python-macos:
|
|
154
|
+
needs: checks
|
|
155
|
+
runs-on: ${{ matrix.platform.runner }}
|
|
156
|
+
strategy:
|
|
157
|
+
fail-fast: false
|
|
158
|
+
matrix:
|
|
159
|
+
platform:
|
|
160
|
+
- runner: macos-15-intel
|
|
161
|
+
target: x86_64
|
|
162
|
+
- runner: macos-latest
|
|
163
|
+
target: aarch64
|
|
164
|
+
steps:
|
|
165
|
+
- uses: actions/checkout@v4
|
|
166
|
+
- uses: actions/setup-python@v5
|
|
167
|
+
with:
|
|
168
|
+
python-version: "3.12"
|
|
169
|
+
- name: Build wheels
|
|
170
|
+
uses: PyO3/maturin-action@v1
|
|
171
|
+
with:
|
|
172
|
+
target: ${{ matrix.platform.target }}
|
|
173
|
+
args: --release --out dist --features python --locked --compatibility pypi
|
|
174
|
+
sccache: "true"
|
|
175
|
+
- uses: actions/upload-artifact@v4
|
|
176
|
+
with:
|
|
177
|
+
name: python-dist-macos-${{ matrix.platform.target }}
|
|
178
|
+
path: dist/*
|
|
179
|
+
if-no-files-found: error
|
|
180
|
+
|
|
181
|
+
build-python-sdist:
|
|
182
|
+
needs: checks
|
|
183
|
+
runs-on: ubuntu-latest
|
|
184
|
+
steps:
|
|
185
|
+
- uses: actions/checkout@v4
|
|
186
|
+
- name: Build sdist
|
|
187
|
+
uses: PyO3/maturin-action@v1
|
|
188
|
+
with:
|
|
189
|
+
command: sdist
|
|
190
|
+
args: --out dist
|
|
191
|
+
- uses: actions/upload-artifact@v4
|
|
192
|
+
with:
|
|
193
|
+
name: python-dist-sdist
|
|
194
|
+
path: dist/*
|
|
195
|
+
if-no-files-found: error
|
|
196
|
+
|
|
197
|
+
publish-pypi:
|
|
198
|
+
needs:
|
|
199
|
+
- build-python-linux
|
|
200
|
+
- build-python-musllinux
|
|
201
|
+
- build-python-windows
|
|
202
|
+
- build-python-macos
|
|
203
|
+
- build-python-sdist
|
|
204
|
+
runs-on: ubuntu-latest
|
|
205
|
+
steps:
|
|
206
|
+
- uses: actions/download-artifact@v4
|
|
207
|
+
with:
|
|
208
|
+
pattern: python-dist-*
|
|
209
|
+
merge-multiple: true
|
|
210
|
+
path: dist
|
|
211
|
+
- uses: actions/setup-python@v5
|
|
212
|
+
with:
|
|
213
|
+
python-version: "3.12"
|
|
214
|
+
- name: Publish Python package to PyPI
|
|
215
|
+
run: |
|
|
216
|
+
pip install maturin
|
|
217
|
+
maturin upload --username __token__ --password "$MATURIN_PYPI_TOKEN" dist/*
|
pyodcs-0.2.0/.gitignore
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Rust
|
|
2
|
+
/target/
|
|
3
|
+
**/*.rs.bk
|
|
4
|
+
|
|
5
|
+
# Editor and OS
|
|
6
|
+
.DS_Store
|
|
7
|
+
*.swp
|
|
8
|
+
*.swo
|
|
9
|
+
*~
|
|
10
|
+
.idea/
|
|
11
|
+
.vscode/
|
|
12
|
+
.cursor/
|
|
13
|
+
*.code-workspace
|
|
14
|
+
|
|
15
|
+
# Environment
|
|
16
|
+
.env
|
|
17
|
+
.env.*
|
|
18
|
+
|
|
19
|
+
# Python
|
|
20
|
+
__pycache__/
|
|
21
|
+
*.py[cod]
|
|
22
|
+
*.so
|
|
23
|
+
*.egg-info/
|
|
24
|
+
.eggs/
|
|
25
|
+
dist/
|
|
26
|
+
.python-version
|
|
27
|
+
venv/
|
|
28
|
+
.venv/
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.2.0
|
|
4
|
+
|
|
5
|
+
First published release.
|
|
6
|
+
|
|
7
|
+
- Phase 1 skeleton milestone (module stubs, fixtures, CLI tests, exit codes)
|
|
8
|
+
- Rust crate `odcs` and Python package `pyodcs`
|
|
9
|
+
- CI and release workflows
|
|
10
|
+
|
|
11
|
+
## 0.1.0
|
|
12
|
+
|
|
13
|
+
Phase 1 — Skeleton (complete).
|
|
14
|
+
|
|
15
|
+
- Professional repository layout aligned with DTCS conventions
|
|
16
|
+
- Rust crate skeleton with full module tree per `crate-layout.md`
|
|
17
|
+
- Basic YAML and JSON parsing for minimal ODCS contracts
|
|
18
|
+
- Extension field preservation on parse
|
|
19
|
+
- CLI: `validate`, `inspect`, `diagnostics`, `schema`, `version` with `--json`
|
|
20
|
+
- CLI exit codes: 0 valid, 1 validation error, 2 parse/IO failure
|
|
21
|
+
- Expanded fixture suite and integration tests (`tests/skeleton.rs`, `tests/cli.rs`)
|
|
22
|
+
- `pyodcs` Python package with PyO3 bindings
|
|
23
|
+
- CI pipeline (fmt, clippy, test) plus release workflow
|
|
24
|
+
- Documentation reorganized under `docs/implementation/`
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Contributing to ODCS
|
|
2
|
+
|
|
3
|
+
Thank you for contributing to the Open Data Contract Standard reference implementation.
|
|
4
|
+
|
|
5
|
+
## Upstream specification
|
|
6
|
+
|
|
7
|
+
Normative ODCS semantics are defined in the [upstream specification](https://github.com/bitol-io/open-data-contract-standard). This repository's [SPEC.md](SPEC.md) documents how we track and synchronize with upstream releases.
|
|
8
|
+
|
|
9
|
+
When implementing behavior:
|
|
10
|
+
|
|
11
|
+
1. Read the relevant upstream ODCS specification sections.
|
|
12
|
+
2. Consult [docs/implementation/](docs/implementation/) for architecture and API guidance.
|
|
13
|
+
3. Preserve spec-aligned naming and behavior.
|
|
14
|
+
4. Add tests that exercise spec requirements. See [docs/implementation/testing-plan.md](docs/implementation/testing-plan.md).
|
|
15
|
+
|
|
16
|
+
### Authority
|
|
17
|
+
|
|
18
|
+
The upstream ODCS specification is the single source of truth for semantics, terminology, and conformance. Implementation docs in [docs/implementation/](docs/implementation/) are illustrative unless explicitly normative.
|
|
19
|
+
|
|
20
|
+
## Implementation changes
|
|
21
|
+
|
|
22
|
+
The Rust reference crate lives in [src/](src/). Before implementing a module:
|
|
23
|
+
|
|
24
|
+
1. Read the relevant upstream specification sections.
|
|
25
|
+
2. Consult [docs/implementation/crate-layout.md](docs/implementation/crate-layout.md) for module boundaries.
|
|
26
|
+
3. Preserve spec-aligned naming and behavior.
|
|
27
|
+
4. Add tests for behavioral changes.
|
|
28
|
+
|
|
29
|
+
### Scope
|
|
30
|
+
|
|
31
|
+
The initial crate targets parsing, the canonical object model, validation, and diagnostics. Do not add execution, pipeline composition, or transformation features without an agreed milestone. See [docs/implementation/non-goals.md](docs/implementation/non-goals.md).
|
|
32
|
+
|
|
33
|
+
### Code style
|
|
34
|
+
|
|
35
|
+
- Run `cargo fmt` and `cargo clippy` before submitting changes.
|
|
36
|
+
- Keep modules aligned with [docs/implementation/crate-layout.md](docs/implementation/crate-layout.md).
|
|
37
|
+
- Prefer conservative behavior when the spec is ambiguous; document open questions with a `TODO` referencing the spec section.
|
|
38
|
+
|
|
39
|
+
## Pull requests
|
|
40
|
+
|
|
41
|
+
1. Describe whether the change is implementation, documentation, or infrastructure.
|
|
42
|
+
2. Link related issues or design discussions when available.
|
|
43
|
+
3. Include or update tests for behavioral changes.
|
|
44
|
+
4. Ensure `cargo test` passes.
|
|
45
|
+
|
|
46
|
+
## Questions
|
|
47
|
+
|
|
48
|
+
For ambiguous upstream spec language, open an issue with the relevant section rather than inventing behavior in code.
|