apc-model-parser 0.1.0__tar.gz → 0.2.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. {apc_model_parser-0.1.0 → apc_model_parser-0.2.1}/AGENTS.md +12 -6
  2. {apc_model_parser-0.1.0 → apc_model_parser-0.2.1}/PKG-INFO +18 -2
  3. {apc_model_parser-0.1.0 → apc_model_parser-0.2.1}/README.md +17 -1
  4. apc_model_parser-0.2.1/docs/chatlogs/2026-06-01_docs-pipx-pypi-install.md +62 -0
  5. apc_model_parser-0.2.1/docs/chatlogs/2026-06-02_model-library-docs-diff-bump.md +63 -0
  6. apc_model_parser-0.2.1/docs/chatlogs/2026-06-03_docs-todo-backlog-mkdocs.md +47 -0
  7. {apc_model_parser-0.1.0 → apc_model_parser-0.2.1}/docs/deployment/ci-cd.md +2 -0
  8. {apc_model_parser-0.1.0 → apc_model_parser-0.2.1}/docs/design/ir-specification.md +3 -1
  9. apc_model_parser-0.2.1/docs/design/model-library-and-versioning.md +147 -0
  10. {apc_model_parser-0.1.0 → apc_model_parser-0.2.1}/docs/design/model-parser.md +8 -1
  11. {apc_model_parser-0.1.0 → apc_model_parser-0.2.1}/docs/index.md +11 -3
  12. apc_model_parser-0.2.1/docs/todo/conformance-fixtures-parity.md +29 -0
  13. apc_model_parser-0.2.1/docs/todo/diff-bump-hardening.md +30 -0
  14. apc_model_parser-0.2.1/docs/todo/emit-cpp-realtime-backend.md +31 -0
  15. apc_model_parser-0.2.1/docs/todo/emit-ini-round-trip.md +31 -0
  16. apc_model_parser-0.2.1/docs/todo/index.md +16 -0
  17. apc_model_parser-0.2.1/docs/todo/ini-dimensions-inference.md +30 -0
  18. apc_model_parser-0.2.1/docs/todo/ir-schema-migrations.md +32 -0
  19. apc_model_parser-0.2.1/docs/todo/parameter-set-contract-cli.md +33 -0
  20. {apc_model_parser-0.1.0 → apc_model_parser-0.2.1}/mkdocs.yml +10 -0
  21. {apc_model_parser-0.1.0 → apc_model_parser-0.2.1}/pyproject.toml +1 -1
  22. {apc_model_parser-0.1.0 → apc_model_parser-0.2.1}/src/model_parser/__init__.py +1 -1
  23. {apc_model_parser-0.1.0 → apc_model_parser-0.2.1}/src/model_parser/cli.py +52 -0
  24. {apc_model_parser-0.1.0 → apc_model_parser-0.2.1}/src/model_parser/frontends/exprtk_ini.py +20 -1
  25. apc_model_parser-0.2.1/src/model_parser/semantic_diff.py +344 -0
  26. {apc_model_parser-0.1.0 → apc_model_parser-0.2.1}/tests/test_cli.py +19 -0
  27. apc_model_parser-0.2.1/tests/test_semantic_diff.py +220 -0
  28. {apc_model_parser-0.1.0 → apc_model_parser-0.2.1}/uv.lock +2 -2
  29. {apc_model_parser-0.1.0 → apc_model_parser-0.2.1}/.github/workflows/ci.yml +0 -0
  30. {apc_model_parser-0.1.0 → apc_model_parser-0.2.1}/.github/workflows/docs.yml +0 -0
  31. {apc_model_parser-0.1.0 → apc_model_parser-0.2.1}/.github/workflows/release.yml +0 -0
  32. {apc_model_parser-0.1.0 → apc_model_parser-0.2.1}/.gitignore +0 -0
  33. {apc_model_parser-0.1.0 → apc_model_parser-0.2.1}/docs/api.md +0 -0
  34. {apc_model_parser-0.1.0 → apc_model_parser-0.2.1}/docs/chatlogs/2026-06-01_bootstrap-model-parser.md +0 -0
  35. {apc_model_parser-0.1.0 → apc_model_parser-0.2.1}/docs/chatlogs/2026-06-01_ci-mkdocs-github-pages-pypi.md +0 -0
  36. {apc_model_parser-0.1.0 → apc_model_parser-0.2.1}/docs/decisions/0001-python-cli-with-julia-backend.md +0 -0
  37. {apc_model_parser-0.1.0 → apc_model_parser-0.2.1}/docs/decisions/0002-codegen-over-serialized-system.md +0 -0
  38. {apc_model_parser-0.1.0 → apc_model_parser-0.2.1}/docs/decisions/0003-explicit-expression-ir.md +0 -0
  39. {apc_model_parser-0.1.0 → apc_model_parser-0.2.1}/docs/decisions/0004-target-mtk-v11-idioms.md +0 -0
  40. {apc_model_parser-0.1.0 → apc_model_parser-0.2.1}/docs/decisions/0005-cli-verbs-parse-emit.md +0 -0
  41. {apc_model_parser-0.1.0 → apc_model_parser-0.2.1}/docs/decisions/index.md +0 -0
  42. {apc_model_parser-0.1.0 → apc_model_parser-0.2.1}/docs/design/language-strategy.md +0 -0
  43. {apc_model_parser-0.1.0 → apc_model_parser-0.2.1}/docs/design/storing-mtk-models.md +0 -0
  44. {apc_model_parser-0.1.0 → apc_model_parser-0.2.1}/examples/README.md +0 -0
  45. {apc_model_parser-0.1.0 → apc_model_parser-0.2.1}/examples/models/model_monod_simple.ini +0 -0
  46. {apc_model_parser-0.1.0 → apc_model_parser-0.2.1}/examples/models/model_thermal_tank.ini +0 -0
  47. {apc_model_parser-0.1.0 → apc_model_parser-0.2.1}/examples/run.sh +0 -0
  48. {apc_model_parser-0.1.0 → apc_model_parser-0.2.1}/julia/ModelParserJL/Project.toml +0 -0
  49. {apc_model_parser-0.1.0 → apc_model_parser-0.2.1}/julia/ModelParserJL/README.md +0 -0
  50. {apc_model_parser-0.1.0 → apc_model_parser-0.2.1}/julia/ModelParserJL/src/ModelParserJL.jl +0 -0
  51. {apc_model_parser-0.1.0 → apc_model_parser-0.2.1}/schemas/canonical-ir.schema.json +0 -0
  52. {apc_model_parser-0.1.0 → apc_model_parser-0.2.1}/src/model_parser/backends/__init__.py +0 -0
  53. {apc_model_parser-0.1.0 → apc_model_parser-0.2.1}/src/model_parser/backends/julia_mtk.py +0 -0
  54. {apc_model_parser-0.1.0 → apc_model_parser-0.2.1}/src/model_parser/frontends/__init__.py +0 -0
  55. {apc_model_parser-0.1.0 → apc_model_parser-0.2.1}/src/model_parser/frontends/expr_parser.py +0 -0
  56. {apc_model_parser-0.1.0 → apc_model_parser-0.2.1}/src/model_parser/io.py +0 -0
  57. {apc_model_parser-0.1.0 → apc_model_parser-0.2.1}/src/model_parser/ir/__init__.py +0 -0
  58. {apc_model_parser-0.1.0 → apc_model_parser-0.2.1}/src/model_parser/ir/expr.py +0 -0
  59. {apc_model_parser-0.1.0 → apc_model_parser-0.2.1}/src/model_parser/ir/model.py +0 -0
  60. {apc_model_parser-0.1.0 → apc_model_parser-0.2.1}/src/model_parser/schema.py +0 -0
  61. {apc_model_parser-0.1.0 → apc_model_parser-0.2.1}/src/model_parser/validation/__init__.py +0 -0
  62. {apc_model_parser-0.1.0 → apc_model_parser-0.2.1}/src/model_parser/validation/validators.py +0 -0
  63. {apc_model_parser-0.1.0 → apc_model_parser-0.2.1}/tests/conftest.py +0 -0
  64. {apc_model_parser-0.1.0 → apc_model_parser-0.2.1}/tests/test_expr_parser.py +0 -0
  65. {apc_model_parser-0.1.0 → apc_model_parser-0.2.1}/tests/test_exprtk_ini.py +0 -0
  66. {apc_model_parser-0.1.0 → apc_model_parser-0.2.1}/tests/test_julia_mtk.py +0 -0
@@ -94,8 +94,8 @@ uv run mkdocs build --strict
94
94
  ### Pure logic vs. I/O separation
95
95
 
96
96
  **Pure modules** parse, normalize, validate, and lower — no filesystem,
97
- subprocess, or network access. Keep `ir/`, `frontends/`, `backends/`, and
98
- `validation/` pure and deterministic.
97
+ subprocess, or network access. Keep `ir/`, `frontends/`, `backends/`,
98
+ `semantic_diff.py`, and `validation/` pure and deterministic.
99
99
 
100
100
  **I/O modules** read/write files and implement the CLI. `io.py` and `cli.py` own
101
101
  filesystem access; the CLI must stay a thin shell over the pure functions.
@@ -133,7 +133,9 @@ never a serialized `System`. Generated Julia targets **MTK v11** idioms
133
133
 
134
134
  Re-running `parse`/`emit` on unchanged input must produce byte-identical output
135
135
  (stable ordering, stable number formatting). The content hash depends only on
136
- the semantic body.
136
+ the semantic body. For `provenance.created_at`, when `SOURCE_DATE_EPOCH` is set
137
+ (see reproducible-builds.org), the INI frontend uses that instant instead of the
138
+ wall clock so regenerated IR JSON stays stable when semantics are unchanged.
137
139
 
138
140
  ### Status vocabulary and exit codes
139
141
 
@@ -149,7 +151,8 @@ CLI diagnostics use `OK` · `WARN` · `ERROR`. Exit codes:
149
151
 
150
152
  - Long options in kebab-case (`--from`, `--profile`, `--output`/`-o`).
151
153
  - The two core verbs are `parse` (authoring → IR) and `emit <target>` (IR →
152
- view). Supporting commands: `validate`, `inspect`, `ast`, `schema`.
154
+ view). Supporting commands: `validate`, `inspect`, `diff`, `bump`, `ast`,
155
+ `schema`.
153
156
  - Breaking CLI changes require a SemVer bump and release notes.
154
157
 
155
158
  ## Scope guardrails
@@ -164,13 +167,16 @@ that *consume* the IR.
164
167
  If a change request conflicts with the design doc, stop and resolve via an
165
168
  explicit doc + ADR update — do not silently expand scope.
166
169
 
167
- ## Work tracking (ADRs and issues)
170
+ ## Work tracking (ADRs, issues, and todos)
168
171
 
169
172
  - **ADRs:** numbered files under [`docs/decisions/`](docs/decisions/) (`NNNN-title.md`),
170
173
  indexed in [`docs/decisions/index.md`](docs/decisions/index.md). One decision per
171
174
  file; never delete — supersede with a newer ADR and update the index.
172
175
  - **Issues:** use GitHub issues for backlog items that are not yet an ADR; link
173
176
  ADRs from issue/PR text when a decision motivates the change.
177
+ - **Todo briefs:** theme-sized notes under [`docs/todo/`](docs/todo/) (`index.md` +
178
+ one file per theme); promote into ADRs or design docs when behaviour is
179
+ decided. Not a substitute for issues or ADRs.
174
180
  - Prefer **small, reviewable slices** (one coherent feature, bugfix, or refactor
175
181
  per PR when practical). For larger work, split PRs and reference the same ADR
176
182
  or design section in each.
@@ -203,7 +209,7 @@ docs may stay in `julia/ModelParserJL/` README until unified.
203
209
 
204
210
  **Intended layout** (keep consistent with [`docs/design/model-parser.md`](docs/design/model-parser.md)):
205
211
 
206
- - `docs/index.md` or root `README.md` — overview, install (`uv`), quick `parse` /
212
+ - `docs/index.md` or root `README.md` — overview, install (PyPI via `pipx` / `uv tool`, dev via `uv`), quick `parse` /
207
213
  `emit` examples (when expanded).
208
214
  - `docs/design/` — product spec (`model-parser.md`) and deep architecture notes.
209
215
  - `docs/decisions/` — ADRs (`NNNN-title.md`) + `index.md`.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: apc-model-parser
3
- Version: 0.1.0
3
+ Version: 0.2.1
4
4
  Summary: Convert process-model definitions to and from a canonical intermediate representation.
5
5
  Project-URL: Repository, https://github.com/Advanced-Process-Control/model-parser
6
6
  Author: Advanced Process Control
@@ -50,7 +50,21 @@ in-memory, dynamic workflows. Both consume the *same* IR. See
50
50
 
51
51
  ## Install
52
52
 
53
- This project uses **[uv](https://docs.astral.sh/uv/)** for everything.
53
+ ### CLI from PyPI (end users)
54
+
55
+ The package on PyPI is **`apc-model-parser`**; the installed command is **`model-parser`**.
56
+
57
+ ```bash
58
+ pipx install apc-model-parser
59
+ # or: uv tool install apc-model-parser
60
+ model-parser --help
61
+ ```
62
+
63
+ Use **`pipx`** or **`uv tool`** when you only need the CLI in an isolated environment.
64
+
65
+ ### From source (development)
66
+
67
+ This repository uses **[uv](https://docs.astral.sh/uv/)** for environments and tasks.
54
68
 
55
69
  ```bash
56
70
  uv sync --all-groups # include dev tools (ruff, pytest, mkdocs)
@@ -69,6 +83,8 @@ uv run model-parser emit julia monod.ir.json -o monod.jl
69
83
  # Supporting commands
70
84
  uv run model-parser validate monod.ir.json --profile julia-analysis
71
85
  uv run model-parser inspect monod.ir.json
86
+ uv run model-parser diff monod.ir.json other.ir.json # semantic IR diff
87
+ uv run model-parser bump monod.ir.json other.ir.json # suggested SemVer bump
72
88
  uv run model-parser ast examples/models/model_monod_simple.ini # debug tree
73
89
  uv run model-parser schema -o schemas/canonical-ir.schema.json # export schema
74
90
  ```
@@ -37,7 +37,21 @@ in-memory, dynamic workflows. Both consume the *same* IR. See
37
37
 
38
38
  ## Install
39
39
 
40
- This project uses **[uv](https://docs.astral.sh/uv/)** for everything.
40
+ ### CLI from PyPI (end users)
41
+
42
+ The package on PyPI is **`apc-model-parser`**; the installed command is **`model-parser`**.
43
+
44
+ ```bash
45
+ pipx install apc-model-parser
46
+ # or: uv tool install apc-model-parser
47
+ model-parser --help
48
+ ```
49
+
50
+ Use **`pipx`** or **`uv tool`** when you only need the CLI in an isolated environment.
51
+
52
+ ### From source (development)
53
+
54
+ This repository uses **[uv](https://docs.astral.sh/uv/)** for environments and tasks.
41
55
 
42
56
  ```bash
43
57
  uv sync --all-groups # include dev tools (ruff, pytest, mkdocs)
@@ -56,6 +70,8 @@ uv run model-parser emit julia monod.ir.json -o monod.jl
56
70
  # Supporting commands
57
71
  uv run model-parser validate monod.ir.json --profile julia-analysis
58
72
  uv run model-parser inspect monod.ir.json
73
+ uv run model-parser diff monod.ir.json other.ir.json # semantic IR diff
74
+ uv run model-parser bump monod.ir.json other.ir.json # suggested SemVer bump
59
75
  uv run model-parser ast examples/models/model_monod_simple.ini # debug tree
60
76
  uv run model-parser schema -o schemas/canonical-ir.schema.json # export schema
61
77
  ```
@@ -0,0 +1,62 @@
1
+ ---
2
+ title: Document PyPI CLI install (pipx and uv tool)
3
+ topic: docs-packaging
4
+ date_added: 2026-06-01
5
+ tags: [chatlogs]
6
+ links:
7
+ - README.md
8
+ - docs/index.md
9
+ - docs/deployment/ci-cd.md
10
+ - AGENTS.md
11
+ ---
12
+
13
+ ## Commit helper
14
+
15
+ - **SemVer / version bump:** **No bump** — documentation only; no change to the
16
+ published package API or CLI contract beyond how to install it.
17
+ - **Tags / GitHub Release:** **None** — stack on `main`; releases remain tag-driven
18
+ when version/metadata changes warrant a new **`v*.*.*`**.
19
+ - **Suggested commit message:** `docs: document pipx and uv tool install for apc-model-parser`
20
+ - **Copy-paste git commands:**
21
+
22
+ ```bash
23
+ git add README.md docs/index.md docs/deployment/ci-cd.md AGENTS.md \
24
+ docs/chatlogs/2026-06-01_docs-pipx-pypi-install.md
25
+ git commit -m 'docs: document pipx and uv tool install for apc-model-parser'
26
+ ```
27
+
28
+ - **Git order when tagging a release:** N/A this session.
29
+
30
+ ## How to try
31
+
32
+ ```bash
33
+ pipx install apc-model-parser
34
+ model-parser --help
35
+
36
+ # Alternative (same CLI, different installer):
37
+ # uv tool install apc-model-parser
38
+
39
+ # Docs site (after deploy):
40
+ # uv run mkdocs build --strict
41
+ ```
42
+
43
+ ## Session narrative
44
+
45
+ **Goal.** After the first PyPI publish and manual **`v0.1.0`** tag, document that
46
+ end users can install the CLI with **`pipx install apc-model-parser`**, not only
47
+ **`uv tool install`**, while keeping **`apc-model-parser`** vs **`model-parser`**
48
+ (dist name vs command) explicit.
49
+
50
+ **Shipped surface.**
51
+
52
+ - **`README.md`:** Install split into **CLI from PyPI** (`pipx` primary, `uv tool`
53
+ comment) and **from source** (`uv sync --all-groups`).
54
+ - **`docs/index.md`:** Published site home — same dual path for PyPI installs;
55
+ short note that both are isolated env installs with `model-parser` on `PATH`.
56
+ - **`docs/deployment/ci-cd.md`:** One line after the release job listing consumer
57
+ **`pipx`** / **`uv tool install`** post-publish.
58
+ - **`AGENTS.md`:** Documentation layout bullet updated to mention PyPI install via
59
+ **`pipx` / `uv tool`** and dev via **`uv`**.
60
+
61
+ **Follow-ups.** None required; optional future “Getting started” page could repeat
62
+ install if the nav grows.
@@ -0,0 +1,63 @@
1
+ ---
2
+ title: Model library design, diff/bump CLI, and model-library bootstrap
3
+ topic: documentation
4
+ date_added: 2026-06-02
5
+ tags: [chatlogs]
6
+ links:
7
+ - AGENTS.md
8
+ - docs/design/model-parser.md
9
+ - docs/design/model-library-and-versioning.md
10
+ - src/model_parser/cli.py
11
+ - src/model_parser/semantic_diff.py
12
+ - src/model_parser/frontends/exprtk_ini.py
13
+ ---
14
+
15
+ ## Commit helper
16
+
17
+ - **SemVer / version bump:** **MINOR** — user-visible CLI (`diff`, `bump`), new pure module `semantic_diff.py`, and `SOURCE_DATE_EPOCH` behaviour for `provenance.created_at` are new public behaviour (not docs-only).
18
+ - **Tags / GitHub Release:** **None** — stack on default branch; tag when maintainers cut a release (existing `release.yml` on tag).
19
+ - **Suggested commit message:** `feat(cli): add IR diff/bump and model-library design doc`
20
+ - **Copy-paste git commands:**
21
+
22
+ ```bash
23
+ git add AGENTS.md README.md docs/design/model-library-and-versioning.md \
24
+ docs/design/model-parser.md docs/design/ir-specification.md \
25
+ docs/index.md docs/chatlogs/2026-06-02_model-library-docs-diff-bump.md \
26
+ mkdocs.yml src/model_parser/cli.py src/model_parser/semantic_diff.py \
27
+ src/model_parser/frontends/exprtk_ini.py tests/test_cli.py tests/test_semantic_diff.py
28
+ git commit -m "$(cat <<'EOF'
29
+ feat(cli): add IR diff/bump and model-library design doc
30
+
31
+ Add semantic comparison and advisory SemVer bump; document library workflows;
32
+ honour SOURCE_DATE_EPOCH for reproducible IR provenance timestamps.
33
+ EOF
34
+ )"
35
+ ```
36
+
37
+ - **Git order when tagging:** commit / push branch (with version bump if releasing) → annotated tag on that commit → push tag.
38
+
39
+ ## How to try
40
+
41
+ ```bash
42
+ cd /path/to/model-parser
43
+ uv sync --all-groups
44
+ uv run model-parser parse examples/models/model_monod_simple.ini -o /tmp/a.ir.json
45
+ uv run model-parser parse examples/models/model_monod_simple.ini -o /tmp/b.ir.json
46
+ uv run model-parser diff /tmp/a.ir.json /tmp/b.ir.json
47
+ uv run model-parser bump /tmp/a.ir.json /tmp/b.ir.json --json
48
+ SOURCE_DATE_EPOCH=946684800 uv run model-parser parse examples/models/model_monod_simple.ini -o /tmp/c.ir.json
49
+ uv run pytest tests/test_semantic_diff.py
50
+ uv run mkdocs build --strict
51
+ ```
52
+
53
+ Sibling repo `model-library`: set `MODEL_PARSER_VENV` to this repo’s `.venv` and run `./scripts/sync.sh` (see that repo’s README).
54
+
55
+ ## Session narrative
56
+
57
+ **Goal:** Capture the prior design answer in-repo, add `diff` / `bump` to support a versioned model library, and bootstrap `Advanced-Process-Control/model-library` with the two existing example models.
58
+
59
+ **Shipped:** New design page `docs/design/model-library-and-versioning.md` (hashes vs SemVer vs git, workflows, authoring vs parameter sets, optimal multi-file layout, reproducible timestamps); nav and cross-links (`mkdocs.yml`, `docs/index.md`, `model-parser.md`, `ir-specification.md`); `src/model_parser/semantic_diff.py` with conservative bump policy; CLI commands `diff` and `bump` (`--json`); INI frontend respects `SOURCE_DATE_EPOCH` for `provenance.created_at`; tests (`tests/test_semantic_diff.py`, CLI smoke); README and `AGENTS.md` updates.
60
+
61
+ **model-library repo:** Added `models/monod_simple` and `models/thermal_tank` with copied authoring INIs, `scripts/sync.sh` + `scripts/update_lock.py`, committed generated `model.ir.json` / `views/model.jl`, `library.lock.json`, README, and GitHub Actions CI that installs `model-parser` from git `main` and fails on drift after sync.
62
+
63
+ **Follow-ups:** Optional ADR for bump policy; `emit ini` and parameter-set JSON remain roadmap; publish a PyPI release so CI can pin a version instead of `main` if desired.
@@ -0,0 +1,47 @@
1
+ ---
2
+ title: Tracked todo briefs under docs/todo and MkDocs nav
3
+ topic: documentation
4
+ date_added: 2026-06-03
5
+ tags: [chatlogs]
6
+ links:
7
+ - AGENTS.md
8
+ - docs/todo/index.md
9
+ - mkdocs.yml
10
+ - docs/index.md
11
+ ---
12
+
13
+ ## Commit helper
14
+
15
+ - **SemVer / version bump:** **no bump** — documentation and contributor-guide updates only (`docs/todo/**`, `mkdocs.yml`, `docs/index.md`, `AGENTS.md`). No user-visible CLI or IR contract change.
16
+ - **Tags / GitHub Release:** **None** — stack on default branch.
17
+ - **Suggested commit message:** `docs: add tracked todo backlog under docs/todo`
18
+ - **Copy-paste git commands:**
19
+
20
+ ```bash
21
+ git add AGENTS.md docs/index.md docs/todo/ mkdocs.yml \
22
+ docs/chatlogs/2026-06-03_docs-todo-backlog-mkdocs.md
23
+ git commit -m "$(cat <<'EOF'
24
+ docs: add tracked todo backlog under docs/todo
25
+
26
+ Add theme-sized future-work briefs, MkDocs Future work nav, and AGENTS work-tracking note.
27
+ EOF
28
+ )"
29
+ ```
30
+
31
+ - **Git order when tagging:** N/A (no release in this slice).
32
+
33
+ ## How to try
34
+
35
+ ```bash
36
+ cd /path/to/model-parser
37
+ uv run mkdocs build --strict
38
+ # optional: open docs/todo/index.md in the editor or browse site → Future work
39
+ ```
40
+
41
+ ## Session narrative
42
+
43
+ **Goal:** Add a `docs/todo/` area with one Markdown file per major future implementation theme, wired into the published docs site, and record guidance on whether `model-library`’s `sync.sh` should auto-commit/push (recommendation: keep sync as regenerate-only; optional separate commit helper; avoid default auto-push).
44
+
45
+ **Shipped:** `docs/todo/index.md` plus seven task files (`emit-ini-round-trip`, `emit-cpp-realtime-backend`, `ir-schema-migrations`, `parameter-set-contract-cli`, `conformance-fixtures-parity`, `ini-dimensions-inference`, `diff-bump-hardening`); `mkdocs.yml` **Future work** nav listing all pages (satisfies `--strict`); link from `docs/index.md`; `AGENTS.md` **Work tracking** section renamed to include todo briefs and clarify they complement ADRs/issues. MkDocs strict fixes: removed invalid links from `docs/` into `src/` / repo root; use code spans or in-repo doc links only.
46
+
47
+ **Follow-ups:** Optional `model-library` script `sync-and-commit.sh` (opt-in commit, no default push) if maintainers want scripted commits; promote individual todo themes into GitHub issues or ADRs when scoped.
@@ -41,6 +41,8 @@ The job:
41
41
  3. Creates a **GitHub Release** (with generated notes) and attaches the built files
42
42
  4. Publishes to **PyPI** using **trusted publishing (OIDC)** — no long-lived API token in secrets
43
43
 
44
+ After publish, end users typically install the CLI with **`pipx install apc-model-parser`** or **`uv tool install apc-model-parser`** (command on `PATH`: **`model-parser`**).
45
+
44
46
  ### PyPI trusted publisher
45
47
 
46
48
  Configure the pending publisher on PyPI for:
@@ -53,7 +53,9 @@ one namespace; duplicates are a validation error.
53
53
 
54
54
  `provenance.content_hash` is `sha256` over the canonical JSON of the IR body
55
55
  **excluding** `provenance`. Downstream artifacts reference a scaffold by this
56
- hash, not by file path.
56
+ hash, not by file path. For how this interacts with a versioned model library,
57
+ SemVer, and git, see
58
+ [`model-library-and-versioning.md`](model-library-and-versioning.md).
57
59
 
58
60
  ## 3. Expression sub-language
59
61
 
@@ -0,0 +1,147 @@
1
+ # Model library, content hashing, and semantic versioning
2
+
3
+ > How a **version-controlled model library** (for example the sibling repository
4
+ > [`Advanced-Process-Control/model-library`](https://github.com/Advanced-Process-Control/model-library))
5
+ > fits the ecosystem, how **`model-parser`** participates without becoming a
6
+ > registry or deployment tool, and how **hashes**, **SemVer**, and **git** play
7
+ > different roles.
8
+
9
+ ## 1. Three axes of “version”
10
+
11
+ Do not collapse these into one number. They answer different questions.
12
+
13
+ | Axis | Question | Mechanism | Analogy |
14
+ |------|-----------|-----------|---------|
15
+ | **Content hash** | Are two scaffolds *semantically identical*? Did anything meaningful change? | `provenance.content_hash` in the IR (`sha256` over the semantic body, excluding `provenance`) | Content-addressed blob id |
16
+ | **Semantic model version** | Is this change backward-compatible for consumers of the scaffold API? | Human or tool-assigned SemVer (e.g. `model.source_version` plus release policy) | Library SemVer |
17
+ | **History / lineage** | Who changed what, when, and why? How do we review, branch, and roll back? | Git commits, tags, PRs | Git history |
18
+
19
+ The content hash is **identity and integrity**, not history. It supports deduplication, cache keys, cross-repository references (“this parameter set was fitted against scaffold `sha256:…`”), and CI checks that regenerated artifacts still match the IR. It does **not** replace git, and it is a poor user-facing release label.
20
+
21
+ See also [`ir-specification.md`](ir-specification.md) (identity / `content_hash`) and [`storing-mtk-models.md`](storing-mtk-models.md) (durable IR + generated `.jl`).
22
+
23
+ ## 2. What the hash is good for
24
+
25
+ - **Drift detection** — Re-emit Julia (or future backends) in CI and assert outputs match expectations, or compare to a lockfile that records per-artifact digests.
26
+ - **Cache keys** — Compiled problems or other caches should key on `content_hash`, target profile, and relevant toolchain versions (see *Storing MTK models* §4).
27
+ - **Pins without paths** — Downstream contracts reference the scaffold by hash, not by repository path (“hashes over file paths” org vocabulary).
28
+ - **Equivalence** — Two authoring files that normalize to the same IR yield the same hash (useful for detecting accidental duplicates or proving a refactor was semantics-preserving).
29
+
30
+ ## 3. Semantic diff and inferred bumps
31
+
32
+ Because expressions live in an **explicit tagged tree** in the IR (not strings; see [ADR 0003](../decisions/0003-explicit-expression-ir.md)), the tool can compare two IRs structurally and suggest a **SemVer bump** for the *model* (distinct from `ir_version`, which versions the IR schema).
33
+
34
+ The CLI exposes:
35
+
36
+ ```text
37
+ model-parser diff <old.ir.json> <new.ir.json> [--json]
38
+ model-parser bump <old.ir.json> <new.ir.json> [--json]
39
+ ```
40
+
41
+ `diff` lists human-readable changes. `bump` prints a suggested bump level:
42
+
43
+ | Level | Typical meaning (conservative policy) |
44
+ |-------|----------------------------------------|
45
+ | `none` | Semantic bodies are identical (`content_hash` match). |
46
+ | `patch` | Documentation-like or bootstrap tweaks only: e.g. `ModelInfo` description / `source_version` / `metadata`, variable `unit` / `description` / `roles`, `profiles`, or **only** numeric **defaults** on existing parameters (same names, same order). |
47
+ | `minor` | **Additive** scaffold API: new parameters **appended** after all previous parameters, with unchanged names and defaults for all previous parameters, and no change to states, inputs, outputs, locals, or equations. |
48
+ | `major` | Anything else: renamed model, changed state/input/output set, changed equations, changed local expressions, removed or reordered parameters, `ir_version` or `independent_variable` change, or any change not covered by `patch` / `minor`. |
49
+
50
+ Policies can evolve; treat `bump` as **advisory** until your library documents stricter rules. When in doubt, the implementation prefers **major** over false compatibility.
51
+
52
+ ## 4. Where logic lives: parser vs library repository
53
+
54
+ **Inside `model-parser` (IR contract, pure logic):**
55
+
56
+ - `parse` / `emit` / `validate` / hashing / JSON Schema.
57
+ - **`diff` and `bump`** — semantic comparison and bump *suggestion* (no git, no catalog).
58
+
59
+ **Inside `model-library` (orchestration, I/O):**
60
+
61
+ - Directory layout, **lockfile** / catalog, CI that regenerates artifacts and fails on drift.
62
+ - Git tags, release notes, and human curation.
63
+
64
+ This keeps `model-parser` small and standalone (see [`model-parser.md`](model-parser.md) §2 and *Non-goals*) while still enabling a “living” multi-representation library.
65
+
66
+ ## 5. Suggested `model-library` layout
67
+
68
+ One directory per model; **one authoring file** is the human edit surface; IR and lowered views are **generated** and committed (or generated only in CI — your choice; the sibling repo defaults to committed artifacts for reviewability).
69
+
70
+ ```text
71
+ models/<name>/
72
+ model.ini # authoring (ExprTk INI today)
73
+ model.ir.json # canonical IR (generated by model-parser parse)
74
+ views/
75
+ model.jl # generated by model-parser emit julia
76
+ library.lock.json # index: names, paths, content_hash, optional view hashes
77
+ ```
78
+
79
+ A thin driver (`scripts/sync.sh`, `just`, or Makefile) invokes the installed `model-parser`. CI runs the same pipeline with `--strict` checks (e.g. `git diff --exit-code` after sync).
80
+
81
+ ## 6. End-to-end workflow
82
+
83
+ ```mermaid
84
+ flowchart TD
85
+ A[Edit models/foo/model.ini] --> B[model-parser parse → model.ir.json]
86
+ B --> C{content_hash changed vs baseline?}
87
+ C -- no --> Z[No semantic change; optional doc-only commit]
88
+ C -- yes --> D[model-parser diff / bump vs previous release IR]
89
+ D --> E[Regenerate views emit julia …]
90
+ E --> F[Update library.lock.json and changelog]
91
+ F --> G[Commit; tag if releasing]
92
+ G --> H[CI: re-sync or re-emit; fail on drift]
93
+ ```
94
+
95
+ Do **not** hand-edit generated `.jl` files; they are compilation products (see [`storing-mtk-models.md`](storing-mtk-models.md)). Planned `emit ini` round-trip (product roadmap) will reduce the need to maintain two authoring encodings by hand.
96
+
97
+ ## 7. Scaffold vs parameter sets vs scenarios (authoring files)
98
+
99
+ The IR intentionally describes the **scaffold** only: structure, equations, roles, units, parameter **declarations** (optional defaults for bootstrap). **Parameter sets** and **scenarios** are **sibling contracts** (fitted values, `x0`/`u0`, horizons) — not stored in the canonical IR as execution truth.
100
+
101
+ ### Current ExprTk INI
102
+
103
+ Today’s frontend documents that **`[x0]` / `[u0]` are dropped** with a warning because they are scenario data ([`model-parser.md`](model-parser.md) §4). **`[Dimensions]`** is still required: it declares how many `x*`, `u*`, and `y*` slots exist before equations are parsed. In principle, counts could be **inferred** from the maximum indices appearing in `dx*`, `y*`, and `u*` references; that would be a **frontend enhancement**, not an IR change.
104
+
105
+ ### Should parameter *values* leave the INI?
106
+
107
+ **Ideal split (org contracts):**
108
+
109
+ - **Scaffold** — declares parameters (names, units, bounds later); optional defaults only for convenience / tests.
110
+ - **Parameter set** — JSON (or similar) referencing the scaffold by **`content_hash`**, carrying the numeric values used for calibration or deployment.
111
+ - **Scenario** — references scaffold (and optionally a parameter set), carries `x0`, `u0`, horizon, etc.
112
+
113
+ Whether values also appear in the INI is a **workflow choice**:
114
+
115
+ - Keeping numeric defaults in INI is convenient for quick `parse → emit` demos and matches legacy MPC files.
116
+ - Moving values entirely into parameter sets is cleaner for **governance** (one hash-pinned scaffold, many value sets) and avoids duplicating “truth” in two places.
117
+
118
+ `model-parser` does not yet ship a parameter-set file format; when the org standardizes one, the library should adopt it alongside the IR.
119
+
120
+ ### Optimal authoring format (if not tied to INI)
121
+
122
+ A greenfield layout often works well as **two or three small files per model** (or one folder):
123
+
124
+ 1. **`scaffold.*`** — YAML or TOML: metadata, symbol tables, equations as structured expressions *or* as controlled strings parsed by the same expression grammar. YAML maps naturally to nested expression trees for tooling.
125
+ 2. **`parameters.default.json`** — optional; references `content_hash` of the IR once emitted, or references `model.name` + lockfile version for humans.
126
+ 3. **`scenario.*`** — initial conditions, setpoints, simulation horizon.
127
+
128
+ The important part is not the concrete syntax but the **separation of concerns** and a single **semantic hub** (the IR) so backends stay renderers, not re-parsers.
129
+
130
+ ## 8. Reproducible provenance timestamps
131
+
132
+ For committed IR JSON, `provenance.created_at` would otherwise change on every regeneration. When **`SOURCE_DATE_EPOCH`** is set (Unix epoch seconds, per [reproducible-builds.org](https://reproducible-builds.org/docs/source-date-epoch/)), the INI frontend uses it for `created_at` instead of the wall clock. Library sync scripts can export this variable so IR files stay byte-stable when semantics are unchanged.
133
+
134
+ ## 9. Larger roadmap (optional)
135
+
136
+ - **Library lockfile** — pins each model’s `content_hash` and digests of generated views; CI verifies them.
137
+ - **`emit ini` round-trip** — product roadmap item; reduces manual dual maintenance of INI and other views.
138
+ - **`ir_version` migrations** — when the IR schema bumps, migration tooling plus ADRs ([`ir-specification.md`](ir-specification.md) §5).
139
+ - **Composite models** — dependency graph of scaffolds; composite content hash derived from constituents (Merkle-style).
140
+ - **Signing / extended provenance** — optional fields for signer identity, git commit SHA, parent scaffold hash (policy and ADR when needed).
141
+
142
+ ## 10. Related documents
143
+
144
+ - [`model-parser.md`](model-parser.md) — product scope and CLI overview.
145
+ - [`ir-specification.md`](ir-specification.md) — IR shape and `content_hash` definition.
146
+ - [`storing-mtk-models.md`](storing-mtk-models.md) — IR + generated `.jl` as durable artifacts.
147
+ - [`language-strategy.md`](language-strategy.md) — Python/Julia split at the IR file boundary.
@@ -85,6 +85,8 @@ model-parser parse <authoring-file> [--from exprtk-ini] [-o out.ir.json]
85
85
  model-parser emit julia <model.ir.json> [-o out.jl]
86
86
  model-parser validate <model.ir.json | authoring-file> [--profile <name>]
87
87
  model-parser inspect <model.ir.json | authoring-file>
88
+ model-parser diff <old.ir.json> <new.ir.json> [--json]
89
+ model-parser bump <old.ir.json> <new.ir.json> [--json]
88
90
  model-parser ast <authoring-file> [-o out.json]
89
91
  model-parser schema [-o schema.json]
90
92
  ```
@@ -97,6 +99,10 @@ model-parser schema [-o schema.json]
97
99
  fly), and an optional `--profile`.
98
100
  - `inspect` prints a human summary; `ast` exports a debug tree; `schema` exports
99
101
  the JSON Schema.
102
+ - `diff` compares two canonical IR files and lists semantic changes; `bump`
103
+ suggests a **SemVer bump** (`none` / `patch` / `minor` / `major`) for the model
104
+ using a conservative policy (see
105
+ [`model-library-and-versioning.md`](model-library-and-versioning.md)).
100
106
 
101
107
  Exit codes: `0` success · `1` validation errors · `2` usage/load failure.
102
108
  Diagnostics use the `OK` / `WARN` / `ERROR` vocabulary.
@@ -131,7 +137,8 @@ model can be valid for Julia analysis while being rejected for a PLC target.
131
137
  ## 8. Roadmap
132
138
 
133
139
  1. **Now (MVP):** ExprTk-INI frontend, canonical IR + schema, core validators,
134
- Julia codegen backend, Julia in-memory loader, example pipeline.
140
+ Julia codegen backend, Julia in-memory loader, example pipeline; semantic
141
+ `diff` / `bump` for library workflows.
135
142
  2. **Conformance:** shared IR fixtures with expected Julia output and (later)
136
143
  expected trajectories, run by both the Python codegen and `ModelParserJL`.
137
144
  3. **Round-trip:** `emit ini` and `export` from a Julia/MTK view back to IR,
@@ -16,16 +16,24 @@ authoring (ExprTk INI) --parse--> AST --normalize--> canonical IR (JSON)
16
16
  ## Where to read next
17
17
 
18
18
  - **[Product specification](design/model-parser.md)** — authoritative scope, CLI, and behaviour.
19
+ - **[Model library & versioning](design/model-library-and-versioning.md)** — hashes, SemVer, sibling `model-library`, authoring vs parameter sets.
20
+ - **[Future work / todos](todo/index.md)** — tracked implementation themes (not a substitute for issues or ADRs).
19
21
  - **[IR specification](design/ir-specification.md)** — IR shape and expression language.
20
22
  - **[Decision log](decisions/index.md)** — ADRs for major design choices.
21
23
  - **[PyPI package `apc-model-parser`](https://pypi.org/project/apc-model-parser/)** — installable CLI (`model-parser`).
22
24
 
23
- ## Install (uv)
25
+ ## Install from PyPI
26
+
27
+ The distribution name is **`apc-model-parser`**; the CLI entry point is **`model-parser`**.
24
28
 
25
29
  ```bash
30
+ pipx install apc-model-parser
31
+ # or:
26
32
  uv tool install apc-model-parser
33
+
27
34
  model-parser --help
28
35
  ```
29
36
 
30
- For development, clone the repository and use `uv sync --all-groups` (see
31
- [CI/CD and releases](deployment/ci-cd.md)).
37
+ **`pipx`** and **`uv tool`** both install the tool into an isolated environment and put `model-parser` on your `PATH`.
38
+
39
+ For **development** from a clone, use **`uv sync --all-groups`** (see [CI/CD and releases](deployment/ci-cd.md)).
@@ -0,0 +1,29 @@
1
+ # TODO: Conformance fixtures and cross-language parity
2
+
3
+ ## Goal
4
+
5
+ Grow **shared IR fixtures** with **expected Julia codegen** (and later
6
+ **expected trajectories** or numerical checks), executed in **Python** and
7
+ **Julia** (`ModelParserJL`) so the two runtimes cannot drift silently.
8
+
9
+ ## Why
10
+
11
+ - [`docs/design/language-strategy.md`](../design/language-strategy.md): the IR
12
+ file is the boundary; parity tests are the enforcement mechanism.
13
+ - Reduces regression risk whenever MTK idioms or codegen change (see ADR 0004).
14
+
15
+ ## Scope hints
16
+
17
+ - Start with golden `.jl` snippets or full files under `tests/` or `examples/`.
18
+ - Julia side: documented `Pkg.test` or script in CI (may remain optional job
19
+ until Julia CI is wired).
20
+
21
+ ## References
22
+
23
+ - [`docs/design/model-parser.md`](../design/model-parser.md) roadmap §2.
24
+ - [ADR 0001](../decisions/0001-python-cli-with-julia-backend.md), [ADR 0004](../decisions/0004-target-mtk-v11-idioms.md).
25
+
26
+ ## Acceptance sketch
27
+
28
+ - At least N≥2 fixtures with checked `emit julia` output.
29
+ - Document how to refresh goldens when codegen intentionally changes.
@@ -0,0 +1,30 @@
1
+ # TODO: Harden `diff` / `bump` for library CI
2
+
3
+ ## Goal
4
+
5
+ Evolve **`model-parser diff`** and **`model-parser bump`** from advisory output
6
+ into optional **CI gates**: stricter classification, exit codes, and documented
7
+ policy for how `model-library` (and others) should interpret results.
8
+
9
+ ## Why
10
+
11
+ - Libraries want “fail if this would be a MAJOR bump without version bump” or
12
+ similar policies.
13
+ - Edge cases (e.g. floating-point literal normalization, metadata-only churn)
14
+ need explicit rules.
15
+
16
+ ## Scope hints
17
+
18
+ - Flags sketch: `--fail-on major`, `--json` stable schema versioning.
19
+ - Extend `src/model_parser/semantic_diff.py` with tests for each policy branch.
20
+ - Cross-link from [`docs/design/model-library-and-versioning.md`](../design/model-library-and-versioning.md).
21
+
22
+ ## References
23
+
24
+ - `src/model_parser/cli.py` (`diff`, `bump`).
25
+ - `tests/test_semantic_diff.py`.
26
+
27
+ ## Acceptance sketch
28
+
29
+ - Documented policy table + tests for CI-oriented flags.
30
+ - Example GitHub Actions snippet in `model-library` or parser deployment docs.
@@ -0,0 +1,31 @@
1
+ # TODO: `emit cpp` (real-time C++ backend)
2
+
3
+ ## Goal
4
+
5
+ Implement **`model-parser emit cpp`** that lowers IR into a **deterministic,
6
+ real-time-safe** C++ representation for PLC / embedded targets, aligned with the
7
+ existing **`realtime-cpp`** validation profile.
8
+
9
+ ## Why
10
+
11
+ - Second major consumer of the same IR after Julia, proving the hub-and-spoke
12
+ design (one expression tree, many renderers).
13
+ - Org roadmap: trajectory or numerical parity checks against the Julia path
14
+ where feasible.
15
+
16
+ ## Scope hints
17
+
18
+ - Constrain to profile-checked operators/functions only; reject or warn clearly.
19
+ - Pure codegen in Python; no new runtime dependency for users who only need IR
20
+ or Julia.
21
+
22
+ ## References
23
+
24
+ - [`docs/design/model-parser.md`](../design/model-parser.md) roadmap §4.
25
+ - `src/model_parser/validation/validators.py` (profile behaviour).
26
+
27
+ ## Acceptance sketch
28
+
29
+ - CLI: `emit cpp` with `-o` path.
30
+ - Tests: small IR fixture and expected `.cpp` (or fragment) under `tests/` or
31
+ `examples/`.