mnesis 0.1.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.
Files changed (73) hide show
  1. mnesis-0.1.0/.github/dependabot.yml +16 -0
  2. mnesis-0.1.0/.github/workflows/ci.yml +95 -0
  3. mnesis-0.1.0/.github/workflows/dependency-review.yml +24 -0
  4. mnesis-0.1.0/.github/workflows/docs.yml +67 -0
  5. mnesis-0.1.0/.github/workflows/publish.yml +309 -0
  6. mnesis-0.1.0/.github/workflows/scorecard.yml +46 -0
  7. mnesis-0.1.0/.gitignore +217 -0
  8. mnesis-0.1.0/CONTRIBUTING.md +169 -0
  9. mnesis-0.1.0/LICENSE +201 -0
  10. mnesis-0.1.0/NOTICE +13 -0
  11. mnesis-0.1.0/PKG-INFO +312 -0
  12. mnesis-0.1.0/README.md +283 -0
  13. mnesis-0.1.0/SECURITY.md +61 -0
  14. mnesis-0.1.0/codecov.yml +15 -0
  15. mnesis-0.1.0/docs/LCM.pdf +0 -0
  16. mnesis-0.1.0/docs/byo-llm.md +124 -0
  17. mnesis-0.1.0/docs/changelog.md +48 -0
  18. mnesis-0.1.0/docs/concepts.md +66 -0
  19. mnesis-0.1.0/docs/configuration.md +102 -0
  20. mnesis-0.1.0/docs/examples.md +82 -0
  21. mnesis-0.1.0/docs/gen_ref_pages.py +53 -0
  22. mnesis-0.1.0/docs/getting-started.md +94 -0
  23. mnesis-0.1.0/docs/images/benchmark_improvement.png +0 -0
  24. mnesis-0.1.0/docs/images/benchmark_scores.png +0 -0
  25. mnesis-0.1.0/docs/images/logo.png +0 -0
  26. mnesis-0.1.0/docs/images/logo_icon.png +0 -0
  27. mnesis-0.1.0/docs/images/logo_wordmark.png +0 -0
  28. mnesis-0.1.0/docs/images/rlm_vs_lcm.png +0 -0
  29. mnesis-0.1.0/docs/index.md +46 -0
  30. mnesis-0.1.0/docs/providers.md +95 -0
  31. mnesis-0.1.0/examples/01_basic_session.py +84 -0
  32. mnesis-0.1.0/examples/02_long_running_agent.py +107 -0
  33. mnesis-0.1.0/examples/03_tool_use.py +143 -0
  34. mnesis-0.1.0/examples/04_large_files.py +196 -0
  35. mnesis-0.1.0/examples/05_parallel_processing.py +156 -0
  36. mnesis-0.1.0/examples/06_byo_llm.py +143 -0
  37. mnesis-0.1.0/mkdocs.yml +74 -0
  38. mnesis-0.1.0/pyproject.toml +124 -0
  39. mnesis-0.1.0/src/mnesis/__init__.py +76 -0
  40. mnesis-0.1.0/src/mnesis/compaction/__init__.py +19 -0
  41. mnesis-0.1.0/src/mnesis/compaction/engine.py +335 -0
  42. mnesis-0.1.0/src/mnesis/compaction/levels.py +307 -0
  43. mnesis-0.1.0/src/mnesis/compaction/pruner.py +252 -0
  44. mnesis-0.1.0/src/mnesis/context/__init__.py +5 -0
  45. mnesis-0.1.0/src/mnesis/context/builder.py +216 -0
  46. mnesis-0.1.0/src/mnesis/events/__init__.py +5 -0
  47. mnesis-0.1.0/src/mnesis/events/bus.py +138 -0
  48. mnesis-0.1.0/src/mnesis/files/__init__.py +5 -0
  49. mnesis-0.1.0/src/mnesis/files/handler.py +445 -0
  50. mnesis-0.1.0/src/mnesis/models/__init__.py +63 -0
  51. mnesis-0.1.0/src/mnesis/models/config.py +233 -0
  52. mnesis-0.1.0/src/mnesis/models/message.py +326 -0
  53. mnesis-0.1.0/src/mnesis/models/summary.py +70 -0
  54. mnesis-0.1.0/src/mnesis/operators/__init__.py +6 -0
  55. mnesis-0.1.0/src/mnesis/operators/agentic_map.py +240 -0
  56. mnesis-0.1.0/src/mnesis/operators/llm_map.py +270 -0
  57. mnesis-0.1.0/src/mnesis/session.py +708 -0
  58. mnesis-0.1.0/src/mnesis/store/__init__.py +29 -0
  59. mnesis-0.1.0/src/mnesis/store/immutable.py +916 -0
  60. mnesis-0.1.0/src/mnesis/store/pool.py +162 -0
  61. mnesis-0.1.0/src/mnesis/store/schema.sql +121 -0
  62. mnesis-0.1.0/src/mnesis/store/summary_dag.py +291 -0
  63. mnesis-0.1.0/src/mnesis/tokens/__init__.py +5 -0
  64. mnesis-0.1.0/src/mnesis/tokens/estimator.py +155 -0
  65. mnesis-0.1.0/tests/__init__.py +0 -0
  66. mnesis-0.1.0/tests/conftest.py +134 -0
  67. mnesis-0.1.0/tests/test_compaction.py +210 -0
  68. mnesis-0.1.0/tests/test_context_builder.py +237 -0
  69. mnesis-0.1.0/tests/test_files.py +106 -0
  70. mnesis-0.1.0/tests/test_operators.py +173 -0
  71. mnesis-0.1.0/tests/test_pruner.py +201 -0
  72. mnesis-0.1.0/tests/test_session.py +277 -0
  73. mnesis-0.1.0/tests/test_store.py +243 -0
@@ -0,0 +1,16 @@
1
+ # To get started with Dependabot version updates, you'll need to specify which
2
+ # package ecosystems to update and where the package manifests are located.
3
+ # Please see the documentation for all configuration options:
4
+ # https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
5
+
6
+ version: 2
7
+ updates:
8
+ - package-ecosystem: "uv"
9
+ directory: "/"
10
+ schedule:
11
+ interval: "weekly"
12
+
13
+ - package-ecosystem: "github-actions"
14
+ directory: "/"
15
+ schedule:
16
+ interval: "weekly"
@@ -0,0 +1,95 @@
1
+ name: CI
2
+ permissions:
3
+ contents: read
4
+
5
+ on:
6
+ push:
7
+ branches: [main]
8
+ paths:
9
+ - "src/**"
10
+ - "tests/**"
11
+ - "pyproject.toml"
12
+ pull_request:
13
+ branches: [main]
14
+ paths:
15
+ - "src/**"
16
+ - "tests/**"
17
+ - "pyproject.toml"
18
+
19
+ jobs:
20
+ lint:
21
+ name: Lint & Format
22
+ runs-on: ubuntu-latest
23
+ steps:
24
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
25
+
26
+ - name: Install uv
27
+ uses: astral-sh/setup-uv@eac588ad8def6316056a12d4907a9d4d84ff7a3b # v7.3.0
28
+ with:
29
+ enable-cache: true
30
+ cache-dependency-glob: "**/pyproject.toml"
31
+ python-version: "3.12"
32
+
33
+ - name: Install dependencies
34
+ run: uv sync --dev
35
+
36
+ - name: Ruff lint
37
+ run: uv run ruff check src/ tests/
38
+
39
+ - name: Ruff format check
40
+ run: uv run ruff format --check src/ tests/
41
+
42
+ typecheck:
43
+ name: Type Check
44
+ runs-on: ubuntu-latest
45
+ steps:
46
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
47
+
48
+ - name: Install uv
49
+ uses: astral-sh/setup-uv@eac588ad8def6316056a12d4907a9d4d84ff7a3b # v7.3.0
50
+ with:
51
+ enable-cache: true
52
+ cache-dependency-glob: "**/pyproject.toml"
53
+ python-version: "3.12"
54
+
55
+ - name: Install dependencies
56
+ run: uv sync --dev
57
+
58
+ - name: mypy
59
+ run: uv run mypy src/mnesis
60
+
61
+ test:
62
+ name: Tests (Python ${{ matrix.python-version }})
63
+ runs-on: ubuntu-latest
64
+ permissions:
65
+ contents: read
66
+ id-token: write
67
+ strategy:
68
+ fail-fast: false
69
+ matrix:
70
+ python-version: ["3.12", "3.13", "3.14"]
71
+ steps:
72
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
73
+
74
+ - name: Install uv
75
+ uses: astral-sh/setup-uv@eac588ad8def6316056a12d4907a9d4d84ff7a3b # v7.3.0
76
+ with:
77
+ enable-cache: true
78
+ cache-dependency-glob: "**/pyproject.toml"
79
+ python-version: ${{ matrix.python-version }}
80
+
81
+ - name: Install dependencies
82
+ run: uv sync --dev
83
+
84
+ - name: Run tests
85
+ env:
86
+ MNESIS_MOCK_LLM: "1"
87
+ run: uv run pytest
88
+
89
+ - name: Upload coverage report
90
+ if: matrix.python-version == '3.12'
91
+ uses: codecov/codecov-action@671740ac38dd9b0130fbe1cec585b89eea48d3de # v5
92
+ with:
93
+ files: coverage.xml
94
+ fail_ci_if_error: false
95
+ use_oidc: true
@@ -0,0 +1,24 @@
1
+ name: Dependency Review
2
+
3
+ on:
4
+ pull_request:
5
+ branches: [main]
6
+
7
+ permissions:
8
+ contents: read
9
+ pull-requests: write # post inline comments on vulnerable deps
10
+
11
+ jobs:
12
+ dependency-review:
13
+ name: Dependency Review
14
+ runs-on: ubuntu-latest
15
+ steps:
16
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
17
+
18
+ - name: Dependency Review
19
+ uses: actions/dependency-review-action@ce3cf9537a52e8119d91fd484ab5b8a807627bf8 # v4.6.0
20
+ with:
21
+ # Fail on any vulnerability severity
22
+ fail-on-severity: low
23
+ # Post a summary comment on the PR
24
+ comment-summary-in-pr: always
@@ -0,0 +1,67 @@
1
+ name: Docs
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ paths:
7
+ - "docs/**"
8
+ - "mkdocs.yml"
9
+ - "src/**"
10
+ pull_request:
11
+ branches: [main]
12
+ paths:
13
+ - "docs/**"
14
+ - "mkdocs.yml"
15
+ - "src/**"
16
+ workflow_dispatch:
17
+
18
+ permissions:
19
+ contents: read
20
+ pages: write
21
+ id-token: write
22
+
23
+ # Only one deployment at a time; don't cancel in-progress runs
24
+ concurrency:
25
+ group: pages
26
+ cancel-in-progress: false
27
+
28
+ jobs:
29
+ build:
30
+ name: Build Docs
31
+ runs-on: ubuntu-latest
32
+ steps:
33
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
34
+ with:
35
+ fetch-depth: 0
36
+
37
+ - name: Install uv
38
+ uses: astral-sh/setup-uv@eac588ad8def6316056a12d4907a9d4d84ff7a3b # v7.3.0
39
+ with:
40
+ enable-cache: true
41
+ cache-dependency-glob: "**/pyproject.toml"
42
+ python-version: "3.12"
43
+
44
+ - name: Install docs dependencies
45
+ run: uv sync --group docs
46
+
47
+ - name: Build docs
48
+ run: uv run mkdocs build
49
+
50
+ - name: Upload pages artifact
51
+ if: github.event_name != 'pull_request'
52
+ uses: actions/upload-pages-artifact@7b1f4a764d45c48632c6b24a0339c27f5614fb0b # v4.0.0
53
+ with:
54
+ path: site/
55
+
56
+ deploy:
57
+ name: Deploy to GitHub Pages
58
+ if: github.event_name != 'pull_request'
59
+ needs: build
60
+ runs-on: ubuntu-latest
61
+ environment:
62
+ name: github-pages
63
+ url: ${{ steps.deployment.outputs.page_url }}
64
+ steps:
65
+ - name: Deploy
66
+ id: deployment
67
+ uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4
@@ -0,0 +1,309 @@
1
+ name: Publish
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ inputs:
6
+ version:
7
+ description: "Version to release (e.g. 0.2.0)"
8
+ required: true
9
+ type: string
10
+ notes:
11
+ description: "Release notes (markdown bullet points). Leave blank to auto-generate from git log."
12
+ required: false
13
+ type: string
14
+
15
+ permissions:
16
+ contents: read
17
+ id-token: write # PyPI OIDC + Sigstore signing
18
+ attestations: write # build provenance attestations
19
+
20
+ jobs:
21
+ # ── 1. Validate inputs ────────────────────────────────────────────────────
22
+ validate:
23
+ name: Validate version
24
+ runs-on: ubuntu-latest
25
+ outputs:
26
+ version: ${{ steps.check.outputs.version }}
27
+ tag: ${{ steps.check.outputs.tag }}
28
+ steps:
29
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
30
+ with:
31
+ fetch-depth: 0
32
+
33
+ - name: Check version format, ordering, and uniqueness
34
+ id: check
35
+ run: |
36
+ VERSION="${{ inputs.version }}"
37
+
38
+ # Must be X.Y.Z (no leading v)
39
+ if ! echo "$VERSION" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+$'; then
40
+ echo "::error::Version '$VERSION' is not valid semver (expected X.Y.Z)"
41
+ exit 1
42
+ fi
43
+
44
+ TAG="v${VERSION}"
45
+
46
+ # Tag must not already exist
47
+ if git rev-parse "$TAG" >/dev/null 2>&1; then
48
+ echo "::error::Tag '$TAG' already exists"
49
+ exit 1
50
+ fi
51
+
52
+ # Changelog must not already have an entry for this version
53
+ if grep -q "^## ${VERSION}" docs/changelog.md; then
54
+ echo "::error::docs/changelog.md already has an entry for ${VERSION}"
55
+ exit 1
56
+ fi
57
+
58
+ # Version must be strictly greater than the latest release tag
59
+ LAST_TAG=$(git tag --sort=-version:refname | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' | head -1)
60
+ if [ -n "$LAST_TAG" ]; then
61
+ LAST_VERSION="${LAST_TAG#v}"
62
+ python3 - <<PYEOF
63
+ import sys
64
+
65
+ def parse(v):
66
+ return tuple(int(x) for x in v.split('.'))
67
+
68
+ new = parse("${VERSION}")
69
+ last = parse("${LAST_VERSION}")
70
+ if new <= last:
71
+ print(f"::error::Version ${VERSION} is not greater than last release ${LAST_VERSION}")
72
+ sys.exit(1)
73
+ print(f"Version ${VERSION} > ${LAST_VERSION} ✓")
74
+ PYEOF
75
+ fi
76
+
77
+ echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
78
+ echo "tag=${TAG}" >> "$GITHUB_OUTPUT"
79
+
80
+ # ── 2. Full CI gate ───────────────────────────────────────────────────────
81
+ lint:
82
+ name: Lint & Format
83
+ needs: validate
84
+ runs-on: ubuntu-latest
85
+ steps:
86
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
87
+
88
+ - name: Install uv
89
+ uses: astral-sh/setup-uv@eac588ad8def6316056a12d4907a9d4d84ff7a3b # v7.3.0
90
+ with:
91
+ enable-cache: true
92
+ cache-dependency-glob: "**/pyproject.toml"
93
+ python-version: "3.12"
94
+
95
+ - name: Install dependencies
96
+ run: uv sync --dev
97
+
98
+ - name: Ruff lint
99
+ run: uv run ruff check src/ tests/
100
+
101
+ - name: Ruff format check
102
+ run: uv run ruff format --check src/ tests/
103
+
104
+ typecheck:
105
+ name: Type Check
106
+ needs: validate
107
+ runs-on: ubuntu-latest
108
+ steps:
109
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
110
+
111
+ - name: Install uv
112
+ uses: astral-sh/setup-uv@eac588ad8def6316056a12d4907a9d4d84ff7a3b # v7.3.0
113
+ with:
114
+ enable-cache: true
115
+ cache-dependency-glob: "**/pyproject.toml"
116
+ python-version: "3.12"
117
+
118
+ - name: Install dependencies
119
+ run: uv sync --dev
120
+
121
+ - name: mypy
122
+ run: uv run mypy src/mnesis
123
+
124
+ test:
125
+ name: Tests (Python ${{ matrix.python-version }})
126
+ needs: validate
127
+ runs-on: ubuntu-latest
128
+ strategy:
129
+ fail-fast: false
130
+ matrix:
131
+ python-version: ["3.12", "3.13", "3.14"]
132
+ steps:
133
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
134
+
135
+ - name: Install uv
136
+ uses: astral-sh/setup-uv@eac588ad8def6316056a12d4907a9d4d84ff7a3b # v7.3.0
137
+ with:
138
+ enable-cache: true
139
+ cache-dependency-glob: "**/pyproject.toml"
140
+ python-version: ${{ matrix.python-version }}
141
+
142
+ - name: Install dependencies
143
+ run: uv sync --dev
144
+
145
+ - name: Run tests
146
+ env:
147
+ MNESIS_MOCK_LLM: "1"
148
+ run: uv run pytest
149
+
150
+ # ── 3. Release ────────────────────────────────────────────────────────────
151
+ release:
152
+ name: Release v${{ needs.validate.outputs.version }}
153
+ needs: [validate, lint, typecheck, test]
154
+ runs-on: ubuntu-latest
155
+ environment: pypi
156
+ steps:
157
+ - name: Generate release token
158
+ id: app-token
159
+ uses: actions/create-github-app-token@29824e69f54612133e76f7eaac726eef6c875baf # v2.2.1
160
+ with:
161
+ app-id: ${{ secrets.RELEASE_APP_ID }}
162
+ private-key: ${{ secrets.RELEASE_APP_PRIVATE_KEY }}
163
+
164
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
165
+ with:
166
+ fetch-depth: 0
167
+ token: ${{ steps.app-token.outputs.token }}
168
+
169
+ - name: Install uv
170
+ uses: astral-sh/setup-uv@eac588ad8def6316056a12d4907a9d4d84ff7a3b # v7.3.0
171
+ with:
172
+ enable-cache: true
173
+ cache-dependency-glob: "**/pyproject.toml"
174
+ python-version: "3.12"
175
+
176
+ - name: Configure git identity
177
+ run: |
178
+ git config user.name "Mnesis Release Bot"
179
+ git config user.email "mnesis-release-bot[bot]@users.noreply.github.com"
180
+
181
+ # ── 3a. Resolve release notes ────────────────────────────────────────
182
+ - name: Resolve release notes
183
+ id: notes
184
+ run: |
185
+ NOTES="${{ inputs.notes }}"
186
+
187
+ if [ -z "$NOTES" ]; then
188
+ LAST_TAG=$(git tag --sort=-version:refname | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' | head -1)
189
+ if [ -n "$LAST_TAG" ]; then
190
+ NOTES=$(git log "${LAST_TAG}..HEAD" --pretty=format:"- %s" --no-merges)
191
+ else
192
+ NOTES=$(git log HEAD --pretty=format:"- %s" --no-merges)
193
+ fi
194
+ fi
195
+
196
+ printf '%s' "$NOTES" > /tmp/release_notes.md
197
+
198
+ echo "notes<<EOF" >> "$GITHUB_OUTPUT"
199
+ printf '%s\n' "$NOTES" >> "$GITHUB_OUTPUT"
200
+ echo "EOF" >> "$GITHUB_OUTPUT"
201
+
202
+ # ── 3b. Bump version in pyproject.toml ──────────────────────────────
203
+ - name: Bump version in pyproject.toml
204
+ run: |
205
+ VERSION="${{ needs.validate.outputs.version }}"
206
+ sed -i "s/^version = \".*\"/version = \"${VERSION}\"/" pyproject.toml
207
+ grep '^version = ' pyproject.toml
208
+
209
+ # ── 3c. Prepend changelog entry ──────────────────────────────────────
210
+ - name: Update docs/changelog.md
211
+ env:
212
+ VERSION: ${{ needs.validate.outputs.version }}
213
+ NOTES: ${{ steps.notes.outputs.notes }}
214
+ run: |
215
+ python3 - <<'PYEOF'
216
+ import pathlib, os, datetime
217
+
218
+ path = pathlib.Path("docs/changelog.md")
219
+ text = path.read_text()
220
+ lines = text.splitlines(keepends=True)
221
+ version = os.environ["VERSION"]
222
+ date = datetime.date.today().strftime("%Y-%m-%d")
223
+ notes = os.environ["NOTES"].strip()
224
+
225
+ insert = 1
226
+ for i, line in enumerate(lines):
227
+ if i == 0:
228
+ continue
229
+ if line.strip() == "" and i == 1:
230
+ insert = 2
231
+ break
232
+
233
+ new_section = f"## {version} — {date}\n\n{notes}\n\n"
234
+ lines.insert(insert, new_section)
235
+ path.write_text("".join(lines))
236
+ print(f"Prepended changelog entry for {version}")
237
+ PYEOF
238
+
239
+ # ── 3d. Build distribution ───────────────────────────────────────────
240
+ # Build before pushing so a build failure leaves the repo untouched.
241
+ - name: Build package
242
+ run: uv build
243
+
244
+ # ── 3e. Attest build provenance ──────────────────────────────────────
245
+ # Generates a Sigstore-signed SLSA provenance attestation for the
246
+ # built artifacts. Attestations are stored in GitHub's attestation
247
+ # store and uploaded to PyPI alongside the package. Users can verify
248
+ # with: gh attestation verify <wheel> --repo Lucenor/mnesis
249
+ - name: Attest build provenance
250
+ uses: actions/attest-build-provenance@e8998f949152b193b063cb0ec769d69d929409be # v2
251
+ with:
252
+ subject-path: dist/*
253
+
254
+ # ── 3f. Generate and attest SBOM ─────────────────────────────────────
255
+ # Generates an SPDX SBOM listing every dependency in the release
256
+ # artifacts, then attests it with Sigstore. Complements provenance
257
+ # ("who built it") with a full dependency inventory ("what's in it").
258
+ - name: Generate SBOM
259
+ uses: anchore/sbom-action@28d71544de8eaf1b958d335707167c5f783590ad # v0.17.0
260
+ with:
261
+ path: dist/
262
+ format: spdx-json
263
+ output-file: sbom.spdx.json
264
+ upload-artifact: false
265
+
266
+ - name: Attest SBOM
267
+ uses: actions/attest-sbom@bd218ad0dbcb3e146bd073d1d9c6d78e08aa8a0b # v2.0.0
268
+ with:
269
+ subject-path: dist/*
270
+ sbom-path: sbom.spdx.json
271
+
272
+ # ── 3g. Commit, tag, push ────────────────────────────────────────────
273
+ - name: Commit and tag release
274
+ run: |
275
+ VERSION="${{ needs.validate.outputs.version }}"
276
+ TAG="${{ needs.validate.outputs.tag }}"
277
+
278
+ git add pyproject.toml docs/changelog.md
279
+ git commit -m "chore: release ${VERSION}"
280
+ git tag -a "$TAG" -m "Release ${VERSION}"
281
+ git push origin main
282
+ git push origin "$TAG"
283
+
284
+ # ── 3h. Create GitHub Release (draft) ───────────────────────────────
285
+ # Created as a draft so it is not subject to release immutability rules.
286
+ # Promoted to published only after PyPI succeeds.
287
+ - name: Create GitHub Release (draft)
288
+ env:
289
+ GH_TOKEN: ${{ steps.app-token.outputs.token }}
290
+ run: |
291
+ TAG="${{ needs.validate.outputs.tag }}"
292
+ gh release create "$TAG" dist/* \
293
+ --title "mnesis ${TAG}" \
294
+ --notes-file /tmp/release_notes.md \
295
+ --draft
296
+
297
+ # ── 3i. Publish to PyPI ──────────────────────────────────────────────
298
+ - name: Publish to PyPI
299
+ uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # release/v1
300
+ with:
301
+ packages-dir: dist/
302
+
303
+ # ── 3j. Publish GitHub Release ───────────────────────────────────────
304
+ - name: Publish GitHub Release
305
+ env:
306
+ GH_TOKEN: ${{ steps.app-token.outputs.token }}
307
+ run: |
308
+ TAG="${{ needs.validate.outputs.tag }}"
309
+ gh release edit "$TAG" --draft=false
@@ -0,0 +1,46 @@
1
+ name: OpenSSF Scorecard
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ schedule:
7
+ # Weekly on Monday at 06:00 UTC
8
+ - cron: "0 6 * * 1"
9
+
10
+ # Restrict default token to read-only; scorecard job elevates as needed.
11
+ permissions: read-all
12
+
13
+ jobs:
14
+ scorecard:
15
+ name: Scorecard analysis
16
+ runs-on: ubuntu-latest
17
+ permissions:
18
+ security-events: write # upload SARIF to GitHub code scanning
19
+ id-token: write # publish results to OpenSSF database
20
+ contents: read
21
+ actions: read
22
+
23
+ steps:
24
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
25
+ with:
26
+ persist-credentials: false
27
+
28
+ - name: Run Scorecard analysis
29
+ uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3
30
+ with:
31
+ results_file: scorecard.sarif
32
+ results_format: sarif
33
+ # Publish results to OpenSSF database for the badge to work
34
+ publish_results: true
35
+
36
+ - name: Upload SARIF artifact
37
+ uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.4.3
38
+ with:
39
+ name: scorecard-sarif
40
+ path: scorecard.sarif
41
+ retention-days: 5
42
+
43
+ - name: Upload SARIF to GitHub code scanning
44
+ uses: github/codeql-action/upload-sarif@f5c2471be782132e47a6e6f9c725e56730d6e9a3 # v3.25.10
45
+ with:
46
+ sarif_file: scorecard.sarif