---
phase: 05-publish-and-deploy
plan: 01
type: execute
wave: 1
depends_on: []
files_modified:
  - pyproject.toml
  - .github/workflows/ci.yml
  - .github/workflows/publish.yml
autonomous: true

must_haves:
  truths:
    - "pyproject.toml requires-python is >=3.10 (dropping EOL Python 3.9)"
    - "ci.yml runs pytest across Python 3.10-3.13 matrix on PRs to main"
    - "ci.yml checks that pyproject.toml version > current PyPI version on PRs to main"
    - "publish.yml builds dist/ in a build job and publishes to PyPI via OIDC in a separate publish job on push to main"
    - "publish job uses environment: pypi and permissions: id-token: write (scoped to job, not workflow)"
  artifacts:
    - path: "pyproject.toml"
      provides: "Package metadata with Python >=3.10 requirement"
      contains: ">=3.10"
    - path: ".github/workflows/ci.yml"
      provides: "PR gate: test matrix + version bump check"
      contains: "pull_request"
    - path: ".github/workflows/publish.yml"
      provides: "PyPI publish via Trusted Publisher OIDC on merge to main"
      contains: "pypa/gh-action-pypi-publish"
  key_links:
    - from: ".github/workflows/publish.yml"
      to: "pyproject.toml"
      via: "python -m build reads pyproject.toml"
      pattern: "python -m build"
    - from: ".github/workflows/ci.yml"
      to: "pyproject.toml"
      via: "pip install -e reads pyproject.toml"
      pattern: 'pip install -e'
---

<objective>
Create the GitHub Actions CI/CD workflows for the meshulash-guard SDK repo and update pyproject.toml to drop EOL Python 3.9 support.

Purpose: Enables automated testing on PRs and automated PyPI publishing on merge to main — the core CI/CD pipeline for the SDK.
Output: Two workflow files (.github/workflows/ci.yml, publish.yml) and an updated pyproject.toml.
</objective>

<execution_context>
@/Users/shalev/.claude/get-shit-done/workflows/execute-plan.md
@/Users/shalev/.claude/get-shit-done/templates/summary.md
</execution_context>

<context>
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/STATE.md
@.planning/phases/05-publish-and-deploy/05-CONTEXT.md
@.planning/phases/05-publish-and-deploy/05-RESEARCH.md
@pyproject.toml
</context>

<tasks>

<task type="auto">
  <name>Task 1: Update pyproject.toml Python version and create CI workflow</name>
  <files>pyproject.toml, .github/workflows/ci.yml</files>
  <action>
1. In `pyproject.toml`, change `requires-python = ">=3.9"` to `requires-python = ">=3.10"` (Python 3.9 is EOL since Oct 2025).

2. Create `.github/workflows/ci.yml` with:
   - Trigger: `pull_request` to `main` branch
   - Two parallel jobs:
     a. `test` job: matrix strategy across Python 3.10, 3.11, 3.12, 3.13. Steps: checkout, setup-python, `pip install -e ".[dev]"`, `pytest`.
     b. `version-check` job: checkout, use `maybe-hello-world/pyproject-check-version@v4` with `pyproject-path: "./pyproject.toml"`. Then a step that fails if `local_version_is_higher == 'false'` with an informative error message showing both versions.

Use exact YAML from 05-RESEARCH.md code examples — those are verified patterns.
  </action>
  <verify>Validate YAML syntax: `python3 -c "import yaml; yaml.safe_load(open('.github/workflows/ci.yml'))"` (install pyyaml if needed). Check pyproject.toml has `>=3.10`.</verify>
  <done>ci.yml exists with test matrix (3.10-3.13) + version check jobs, pyproject.toml requires Python >=3.10</done>
</task>

<task type="auto">
  <name>Task 2: Create PyPI publish workflow</name>
  <files>.github/workflows/publish.yml</files>
  <action>
Create `.github/workflows/publish.yml` with the two-job pattern from 05-RESEARCH.md:

- Trigger: `push` to `main` branch
- Job 1 (`build`): checkout, setup-python (3.x), install `build`, run `python -m build`, upload dist/ as artifact (`python-package-distributions`)
- Job 2 (`publish`): needs `build`, environment `pypi` with URL `https://pypi.org/p/meshulash-guard`, permissions `id-token: write` (JOB-level only, NOT workflow-level). Download artifact, use `pypa/gh-action-pypi-publish@release/v1`.

CRITICAL: `id-token: write` must be on the `publish` job only, not at workflow level. This is a security requirement.

Use exact YAML from 05-RESEARCH.md code examples.
  </action>
  <verify>Validate YAML syntax: `python3 -c "import yaml; yaml.safe_load(open('.github/workflows/publish.yml'))"`. Verify `id-token: write` appears only under the publish job's permissions, not at workflow level.</verify>
  <done>publish.yml exists with build+publish two-job pattern, id-token scoped to publish job only, environment set to "pypi"</done>
</task>

</tasks>

<verification>
1. `cat pyproject.toml | grep requires-python` shows `>=3.10`
2. `ls .github/workflows/` shows `ci.yml` and `publish.yml`
3. Both YAML files parse without errors
4. `grep -n "id-token" .github/workflows/publish.yml` shows it only under the publish job section
5. `grep "environment" .github/workflows/publish.yml` shows `name: pypi`
</verification>

<success_criteria>
- pyproject.toml updated to require Python >=3.10
- ci.yml triggers on PRs to main with test matrix + version check
- publish.yml triggers on push to main with two-job build+publish pattern
- OIDC permissions correctly scoped to publish job only
</success_criteria>

<output>
After completion, create `.planning/phases/05-publish-and-deploy/05-01-SUMMARY.md`
</output>
