diff --git a/.github/ISSUE_TEMPLATE/gp-01.yml b/.github/ISSUE_TEMPLATE/gp-01.yml new file mode 100644 index 00000000..fceb1fde --- /dev/null +++ b/.github/ISSUE_TEMPLATE/gp-01.yml @@ -0,0 +1,113 @@ +name: "GP-01 — GEMS Language evolution impact on GemsPy" +description: Track updates to the GemsPy interpreter triggered by a new GEMS Language version +title: "[GP-01] GEMS Language update — GemsPy impact" +labels: ["GP-01", "gems-language-update"] +body: + - type: markdown + attributes: + value: | + **Process GP-01** — Triggered by a new GEMS Language version that requires changes to GemsPy parsing, execution, or behavior. + + > **Deviation from standard workflow — Step 4:** introduce version-gated behavior if needed; GemsPy must support multiple GEMS Language versions simultaneously; update parsing and execution layers accordingly. + + - type: input + id: gems_new_version + attributes: + label: New GEMS Language Version + placeholder: "e.g. 1.3.0" + validations: + required: true + + - type: input + id: gems_previous_version + attributes: + label: Previous Tracked Version + placeholder: "e.g. 1.2.0" + validations: + required: true + + - type: textarea + id: trigger + attributes: + label: Trigger + description: What changed in the new GEMS Language version? Link to the GEMS release notes or changelog. + validations: + required: true + + - type: textarea + id: impact + attributes: + label: Impact Analysis + description: | + Assess the impact on: + - **Grammar** — does `grammar/Expr.g4` need updating? + - **Parsing layer** — does the ANTLR-generated parser or expression AST need updating? + - **Execution layer** — does model loading, constraint building, or variable resolution need updating? + - **Version-gated behavior** — does GemsPy need to support both old and new syntax simultaneously? + - **Results** — are solver output values expected to change? + - **Compatibility** — breaking vs backward-compatible? + validations: + required: true + + - type: textarea + id: validation_strategy + attributes: + label: Validation Strategy + description: | + Describe the regression and E2E validation approach: + - Which reference studies cover the new/changed syntax? + - Are solver results expected to differ? If yes, why? + - How will backward compatibility with old syntax be verified? + validations: + required: true + + - type: textarea + id: checklist + attributes: + label: Process Checklist + value: | + ### Step 1 — Issue Creation + - [x] Issue created and linked to process GP-01 + + ### Step 2 — Triage + - [ ] Process confirmed applicable + - [ ] Assigned to responsible contributor + - [ ] Priority and milestone set (if applicable) + + ### Step 3 — Impact Analysis + - [ ] GEMS Language changelog reviewed for GemsPy-relevant changes + - [ ] Grammar impact assessed (`grammar/Expr.g4`) + - [ ] Parsing layer impact assessed (`expression/`, ANTLR-generated files) + - [ ] Execution layer impact assessed (`simulation/`, `study/`) + - [ ] Version-gated behavior required? (yes/no — document decision) + - [ ] Results impact assessed (solver values expected to change?) + - [ ] Breaking vs backward-compatible change identified + + ### Step 4 — Implementation ⚠️ version-gated behavior may be required + - [ ] Grammar updated (`grammar/Expr.g4`) if needed — do not edit ANTLR-generated files directly + - [ ] ANTLR parser regenerated if grammar changed + - [ ] Parsing and execution layers updated (`expression/`, `simulation/`, `study/`) + - [ ] Version-gated behavior introduced if GemsPy must support both old and new syntax + + ### Step 5 — Testing & Validation ⚠️ regression suite covering old and new syntax required + - [ ] At least one reference E2E study validating new language feature added or updated + - [ ] Regression tests covering old syntax still pass + - [ ] If results expected to change: before/after comparison documented + - [ ] If results must not change: confirmed via tests + + ### Step 6 — CI Validation + - [ ] Type checking passes (`mypy`) + - [ ] Formatting passes (`black`, `isort`) + - [ ] All tests pass in CI (`pytest`) + + ### Step 7 — Review & Merge + - [ ] PR reviewed; documentation changes included + + ### Step 8 — Versioning + - [ ] `pyproject.toml` version bumped (Major if breaking language change, Minor otherwise) + + ### Step 9 — Supporting Files + - [ ] `AGENTS.md` reviewed for impact and updated if needed + + ### Step 10 — Release + - [ ] If a release is needed: follow the release process in the Developer Guidelines diff --git a/.github/ISSUE_TEMPLATE/gp-02.yml b/.github/ISSUE_TEMPLATE/gp-02.yml new file mode 100644 index 00000000..28a42926 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/gp-02.yml @@ -0,0 +1,113 @@ +name: "GP-02 — GemsPy internal development" +description: Track internal bug fixes, new GemsPy features, or code improvements not driven by a GEMS Language release +title: "[GP-02] " +labels: ["GP-02"] +body: + - type: markdown + attributes: + value: | + **Process GP-02** — Triggered by internal initiative to fix, improve, or extend GemsPy. Not driven by a new GEMS Language version. + + > **Deviation from standard workflow — Step 3:** extended impact analysis on results is required. You must explicitly state whether solver results are expected to change, and if so, document the reasoning. + + - type: dropdown + id: component + attributes: + label: Affected Component + options: + - Expression parsing / grammar (expression/, grammar/) + - Optimization problem construction (simulation/) + - Study loading / model resolution (study/) + - Decomposition / optim-config (optim_config/) + - Library resolution (libs/) + - Other (specify in description) + validations: + required: true + + - type: dropdown + id: change_type + attributes: + label: Type of Change + description: Determines the semantic version impact. + options: + - "Major: backward-incompatible change or major new feature (e.g. rolling horizon)" + - "Minor: bug fix or backward-compatible new feature (e.g. new operator)" + - "Patch: dependency update, code optimisation, or internal refactor with no syntax impact" + validations: + required: true + + - type: textarea + id: description + attributes: + label: Description + description: What change is being proposed and why? + validations: + required: true + + - type: textarea + id: results_impact + attributes: + label: Results Impact + description: | + Are solver output values expected to change? + - If yes: describe the before/after difference and why it is intended. + - If no: this must be confirmed via tests. + validations: + required: true + + - type: textarea + id: validation_strategy + attributes: + label: Validation Strategy + description: | + Describe the validation approach: + - Which unit tests cover the changed component? + - Which E2E studies confirm solver equivalence (if results must not change)? + - If results are expected to change, which reference studies document the new expected behavior? + validations: + required: true + + - type: textarea + id: checklist + attributes: + label: Process Checklist + value: | + ### Step 1 — Issue Creation + - [x] Issue created and linked to process GP-02 + + ### Step 2 — Triage + - [ ] Process confirmed applicable + - [ ] Assigned to responsible contributor + - [ ] Priority and milestone set (if applicable) + + ### Step 3 — Impact Analysis ⚠️ extended results analysis required + - [ ] Affected modules identified + - [ ] Results impact explicitly stated: change intended / no change intended + - [ ] If results expected to change: before/after difference described and justified + - [ ] Breaking vs backward-compatible change determined + + ### Step 4 — Implementation + - [ ] Code changes implemented + - [ ] Backward compatibility maintained unless explicitly intended as breaking + + ### Step 5 — Testing & Validation + - [ ] If results expected to change: reference studies updated with new expected values + - [ ] If results must not change: solver equivalence confirmed via tests + - [ ] Unit tests cover changed components + + ### Step 6 — CI Validation + - [ ] Type checking passes (`mypy`) + - [ ] Formatting passes (`black`, `isort`) + - [ ] All tests pass in CI (`pytest`) + + ### Step 7 — Review & Merge + - [ ] PR reviewed; documentation changes included + + ### Step 8 — Versioning + - [ ] `pyproject.toml` version bumped + + ### Step 9 — Supporting Files + - [ ] `AGENTS.md` reviewed for impact and updated if needed + + ### Step 10 — Release + - [ ] If a release is needed: follow the release process in the Developer Guidelines diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 00000000..2bb774b5 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,23 @@ +## Process ID + + + + +**Process:** + +## Description + + + +## Impact Analysis + + + + +## Checklist + +- [ ] Unit tests pass (`pytest`) +- [ ] Type checking passes (`mypy`) +- [ ] Formatting passes (`black`, `isort`) +- [ ] `pyproject.toml` version bumped if applicable +- [ ] `AGENTS.md` reviewed for impact and updated if needed diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2778d5a8..09ccaf09 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,10 +11,10 @@ jobs: runs-on: ubuntu-22.04 steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v6 - name: Set up Python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: 3.11 diff --git a/.github/workflows/notify-gemspy-release.yml b/.github/workflows/notify-gemspy-release.yml new file mode 100644 index 00000000..6e6056ad --- /dev/null +++ b/.github/workflows/notify-gemspy-release.yml @@ -0,0 +1,165 @@ +name: Notify dependents — GemsPy new release + +on: + release: + types: [published] + +permissions: + contents: read + +jobs: + notify: + name: Create issue in dependent repositories + runs-on: ubuntu-latest + + steps: + - name: Get release version + id: version + run: | + VERSION="${{ github.event.release.tag_name }}" + VERSION="${VERSION#v}" + echo "version=$VERSION" >> "$GITHUB_OUTPUT" + echo "Released version: $VERSION" + + - name: Notify GEMS repository + uses: actions/github-script@v9 + with: + github-token: ${{ secrets.GEMS_REPO_PAT }} + script: | + const version = '${{ steps.version.outputs.version }}'; + const title = `[GEMSPY UPDATE] New release: v${version}`; + const owner = context.repo.owner; + + const existing = await github.rest.issues.listForRepo({ + owner: owner, + repo: 'GEMS', + state: 'open', + }); + + const duplicate = existing.data.find(i => i.title.includes(`v${version}`)); + if (duplicate) { + console.log(`Issue already exists in GEMS: #${duplicate.number} — skipping.`); + return; + } + + const body = [ + '> This issue was automatically created by the `notify-gemspy-release` workflow in GemsPy.', + '', + '## New Version Detected', + '', + '| | |', + '|---|---|', + `| **New version** | \`${version}\` |`, + `| **PyPI page** | https://pypi.org/project/gemspy/${version}/ |`, + `| **Release notes** | https://github.com/${owner}/GemsPy/releases/tag/v${version} |`, + '', + '## Triage', + '', + '- [ ] GemsPy changelog reviewed', + '- [ ] No action needed (if release has no impact on GEMS)', + ].join('\n'); + + const result = await github.rest.issues.create({ + owner: owner, + repo: 'GEMS', + title: title, + body: body, + }); + + console.log(`Issue created in GEMS: #${result.data.number} — ${result.data.html_url}`); + + - name: Notify AntaresLegacyModels-to-GEMS-Converter repository + uses: actions/github-script@v9 + with: + github-token: ${{ secrets.ANTARES_LEGACY_CONVERTER_PAT }} + script: | + const version = '${{ steps.version.outputs.version }}'; + const title = `[GEMSPY UPDATE] New release: v${version}`; + const owner = context.repo.owner; + + const existing = await github.rest.issues.listForRepo({ + owner: owner, + repo: 'AntaresLegacyModels-to-GEMS-Converter', + state: 'open', + }); + + const duplicate = existing.data.find(i => i.title.includes(`v${version}`)); + if (duplicate) { + console.log(`Issue already exists in AntaresLegacyModels-to-GEMS-Converter: #${duplicate.number} — skipping.`); + return; + } + + const body = [ + '> This issue was automatically created by the `notify-gemspy-release` workflow in GemsPy.', + '', + '## New Version Detected', + '', + '| | |', + '|---|---|', + `| **New version** | \`${version}\` |`, + `| **PyPI page** | https://pypi.org/project/gemspy/${version}/ |`, + `| **Release notes** | https://github.com/${owner}/GemsPy/releases/tag/v${version} |`, + '', + '## Triage', + '', + '- [ ] GemsPy changelog reviewed', + '- [ ] A2G-04 issue opened (if API changes affect GEMS study generation, model validation, or simulation output)', + '- [ ] No action needed (if release has no impact on the converter)', + ].join('\n'); + + const result = await github.rest.issues.create({ + owner: owner, + repo: 'AntaresLegacyModels-to-GEMS-Converter', + title: title, + body: body, + }); + + console.log(`Issue created in AntaresLegacyModels-to-GEMS-Converter: #${result.data.number} — ${result.data.html_url}`); + + - name: Notify GEMS-ViewsBuilder repository + uses: actions/github-script@v9 + with: + github-token: ${{ secrets.GEMS_VIEWS_BUILDER_PAT }} + script: | + const version = '${{ steps.version.outputs.version }}'; + const title = `[GEMSPY UPDATE] New release: v${version}`; + const owner = context.repo.owner; + + const existing = await github.rest.issues.listForRepo({ + owner: owner, + repo: 'GEMS-ViewsBuilder', + state: 'open', + }); + + const duplicate = existing.data.find(i => i.title.includes(`v${version}`)); + if (duplicate) { + console.log(`Issue already exists in GEMS-ViewsBuilder: #${duplicate.number} — skipping.`); + return; + } + + const body = [ + '> This issue was automatically created by the `notify-gemspy-release` workflow in GemsPy.', + '', + '## New Version Detected', + '', + '| | |', + '|---|---|', + `| **New version** | \`${version}\` |`, + `| **PyPI page** | https://pypi.org/project/gemspy/${version}/ |`, + `| **Release notes** | https://github.com/${owner}/GemsPy/releases/tag/v${version} |`, + '', + '## Triage', + '', + '- [ ] GemsPy changelog reviewed', + '- [ ] `gemspy` dependency version updated in `pyproject.toml` (if new features or fixes are required)', + '- [ ] No action needed (if release has no impact on GEMS-ViewsBuilder)', + ].join('\n'); + + const result = await github.rest.issues.create({ + owner: owner, + repo: 'GEMS-ViewsBuilder', + title: title, + body: body, + }); + + console.log(`Issue created in GEMS-ViewsBuilder: #${result.data.number} — ${result.data.html_url}`); diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 69d6bd6c..6ee6ea13 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -22,9 +22,9 @@ jobs: environment: PyPi steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Set up Python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: '3.11' diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000..57af52b2 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,5 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +For full project context, architecture, conventions, and critical rules, see [AGENTS.md](AGENTS.md) — read it before making any changes.