logodev-mcp 1.0.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 (90) hide show
  1. logodev_mcp-1.0.0/.copier-answers.yml +13 -0
  2. logodev_mcp-1.0.0/.env.example +30 -0
  3. logodev_mcp-1.0.0/.gemini/config.yaml +18 -0
  4. logodev_mcp-1.0.0/.gitattributes +3 -0
  5. logodev_mcp-1.0.0/.github/codeql/codeql-config.yml +7 -0
  6. logodev_mcp-1.0.0/.github/dependabot.yml +15 -0
  7. logodev_mcp-1.0.0/.github/workflows/ci.yml +332 -0
  8. logodev_mcp-1.0.0/.github/workflows/claude-code-review.yml +58 -0
  9. logodev_mcp-1.0.0/.github/workflows/claude.yml +55 -0
  10. logodev_mcp-1.0.0/.github/workflows/codeql.yml +31 -0
  11. logodev_mcp-1.0.0/.github/workflows/copier-update.yml +564 -0
  12. logodev_mcp-1.0.0/.github/workflows/coverage-status.yml +53 -0
  13. logodev_mcp-1.0.0/.github/workflows/docs.yml +118 -0
  14. logodev_mcp-1.0.0/.github/workflows/release.yml +485 -0
  15. logodev_mcp-1.0.0/.gitignore +48 -0
  16. logodev_mcp-1.0.0/.gitleaks.toml +8 -0
  17. logodev_mcp-1.0.0/.pre-commit-config.yaml +98 -0
  18. logodev_mcp-1.0.0/.vale/styles/config/vocabularies/Base/accept.txt +49 -0
  19. logodev_mcp-1.0.0/.vale.ini +52 -0
  20. logodev_mcp-1.0.0/CHANGELOG.md +4 -0
  21. logodev_mcp-1.0.0/CLAUDE.md +200 -0
  22. logodev_mcp-1.0.0/Dockerfile +72 -0
  23. logodev_mcp-1.0.0/FORKING.md +88 -0
  24. logodev_mcp-1.0.0/LICENSE +55 -0
  25. logodev_mcp-1.0.0/PKG-INFO +224 -0
  26. logodev_mcp-1.0.0/README.md +199 -0
  27. logodev_mcp-1.0.0/codecov.yml +33 -0
  28. logodev_mcp-1.0.0/compose.yml +23 -0
  29. logodev_mcp-1.0.0/docker-entrypoint.sh +48 -0
  30. logodev_mcp-1.0.0/docs/configuration-generator.md +11 -0
  31. logodev_mcp-1.0.0/docs/configuration.md +17 -0
  32. logodev_mcp-1.0.0/docs/deployment/claude-desktop.md +101 -0
  33. logodev_mcp-1.0.0/docs/deployment/docker.md +87 -0
  34. logodev_mcp-1.0.0/docs/deployment/oidc.md +209 -0
  35. logodev_mcp-1.0.0/docs/guides/authentication.md +237 -0
  36. logodev_mcp-1.0.0/docs/index.md +21 -0
  37. logodev_mcp-1.0.0/docs/installation.md +27 -0
  38. logodev_mcp-1.0.0/docs/javascripts/config-wizard/generators.js +210 -0
  39. logodev_mcp-1.0.0/docs/javascripts/config-wizard/wizard-spec-schema.json +116 -0
  40. logodev_mcp-1.0.0/docs/javascripts/config-wizard/wizard-spec.json +46 -0
  41. logodev_mcp-1.0.0/docs/javascripts/config-wizard/wizard.js +265 -0
  42. logodev_mcp-1.0.0/docs/prompts.md +25 -0
  43. logodev_mcp-1.0.0/docs/stylesheets/config-wizard.css +21 -0
  44. logodev_mcp-1.0.0/docs/tools/index.md +35 -0
  45. logodev_mcp-1.0.0/examples/bearer-auth.env +5 -0
  46. logodev_mcp-1.0.0/examples/oidc.env +9 -0
  47. logodev_mcp-1.0.0/mkdocs.yml +123 -0
  48. logodev_mcp-1.0.0/packaging/env.example +19 -0
  49. logodev_mcp-1.0.0/packaging/logodev-mcp.service +80 -0
  50. logodev_mcp-1.0.0/packaging/mcpb/.gitignore +3 -0
  51. logodev_mcp-1.0.0/packaging/mcpb/build.sh +53 -0
  52. logodev_mcp-1.0.0/packaging/mcpb/manifest.json.in +64 -0
  53. logodev_mcp-1.0.0/packaging/mcpb/pyproject.toml.in +12 -0
  54. logodev_mcp-1.0.0/packaging/mcpb/src/server.py +20 -0
  55. logodev_mcp-1.0.0/packaging/nfpm.yaml +68 -0
  56. logodev_mcp-1.0.0/packaging/scripts/postinstall.sh +53 -0
  57. logodev_mcp-1.0.0/packaging/scripts/postremove.sh +28 -0
  58. logodev_mcp-1.0.0/packaging/scripts/preinstall.sh +20 -0
  59. logodev_mcp-1.0.0/packaging/scripts/preremove.sh +24 -0
  60. logodev_mcp-1.0.0/packaging/test-install.sh +168 -0
  61. logodev_mcp-1.0.0/pyproject.toml +189 -0
  62. logodev_mcp-1.0.0/scripts/bump_manifests.py +108 -0
  63. logodev_mcp-1.0.0/scripts/copier_update_aggregator.py +573 -0
  64. logodev_mcp-1.0.0/scripts/copier_update_prompts/job_a.md +132 -0
  65. logodev_mcp-1.0.0/scripts/copier_update_prompts/job_b.md +81 -0
  66. logodev_mcp-1.0.0/scripts/copier_update_prompts/job_c.md +82 -0
  67. logodev_mcp-1.0.0/scripts/vendor_spa.py +18 -0
  68. logodev_mcp-1.0.0/server.json +172 -0
  69. logodev_mcp-1.0.0/src/logodev_mcp/__init__.py +6 -0
  70. logodev_mcp-1.0.0/src/logodev_mcp/_server_apps.py +37 -0
  71. logodev_mcp-1.0.0/src/logodev_mcp/_server_deps.py +49 -0
  72. logodev_mcp-1.0.0/src/logodev_mcp/cli.py +118 -0
  73. logodev_mcp-1.0.0/src/logodev_mcp/config.py +48 -0
  74. logodev_mcp-1.0.0/src/logodev_mcp/domain.py +270 -0
  75. logodev_mcp-1.0.0/src/logodev_mcp/prompts.py +21 -0
  76. logodev_mcp-1.0.0/src/logodev_mcp/resources.py +34 -0
  77. logodev_mcp-1.0.0/src/logodev_mcp/server.py +121 -0
  78. logodev_mcp-1.0.0/src/logodev_mcp/static/app.html +13 -0
  79. logodev_mcp-1.0.0/src/logodev_mcp/static/icons/.gitkeep +0 -0
  80. logodev_mcp-1.0.0/src/logodev_mcp/tools.py +163 -0
  81. logodev_mcp-1.0.0/tests/conftest.py +28 -0
  82. logodev_mcp-1.0.0/tests/test_cli.py +40 -0
  83. logodev_mcp-1.0.0/tests/test_config.py +23 -0
  84. logodev_mcp-1.0.0/tests/test_config_wizard_domain.py +30 -0
  85. logodev_mcp-1.0.0/tests/test_config_wizard_smoke.py +336 -0
  86. logodev_mcp-1.0.0/tests/test_config_wizard_spec_schema.py +178 -0
  87. logodev_mcp-1.0.0/tests/test_domain.py +421 -0
  88. logodev_mcp-1.0.0/tests/test_smoke.py +131 -0
  89. logodev_mcp-1.0.0/tests/test_tools.py +125 -0
  90. logodev_mcp-1.0.0/uv.lock +3097 -0
@@ -0,0 +1,13 @@
1
+ # Changes here will be overwritten by `copier update`.
2
+ _commit: v2.5.3
3
+ _src_path: gh:pvliesdonk/fastmcp-server-template
4
+ docker_registry: ghcr.io/pvliesdonk
5
+ domain_description: Look up company logos and brand data via the logo.dev API.
6
+ enable_authorization: false
7
+ env_prefix: LOGODEV_MCP
8
+ github_org: pvliesdonk
9
+ human_name: Logo.dev MCP
10
+ include_mcp_apps_scaffold: false
11
+ project_name: logodev-mcp
12
+ pypi_name: logodev-mcp
13
+ python_module: logodev_mcp
@@ -0,0 +1,30 @@
1
+ # Logo.dev MCP environment variables (copy to .env and fill in).
2
+
3
+ # --- Server ---
4
+ # LOGODEV_MCP_TRANSPORT=stdio # stdio | http | sse
5
+ # LOGODEV_MCP_HOST=127.0.0.1
6
+ # LOGODEV_MCP_PORT=8000
7
+ # LOGODEV_MCP_HTTP_PATH=/mcp
8
+ # LOGODEV_MCP_BASE_URL=https://mcp.example.com
9
+
10
+ # --- Authentication (pick one flavor) ---
11
+ # LOGODEV_MCP_BEARER_TOKEN=<secret>
12
+
13
+ # LOGODEV_MCP_BEARER_TOKENS_FILE=/etc/logodev-mcp/tokens.toml # mapped per-token subjects (overrides BEARER_TOKEN)
14
+
15
+ # LOGODEV_MCP_OIDC_CONFIG_URL=https://auth.example.com/.well-known/openid-configuration
16
+ # LOGODEV_MCP_OIDC_CLIENT_ID=<client-id>
17
+ # LOGODEV_MCP_OIDC_CLIENT_SECRET=<client-secret>
18
+ # LOGODEV_MCP_OIDC_AUDIENCE=
19
+ # LOGODEV_MCP_OIDC_REQUIRED_SCOPES=openid
20
+ # LOGODEV_MCP_OIDC_JWT_SIGNING_KEY=<hex-string>
21
+
22
+ # --- Remote debugger (development only — image must be built with --build-arg DEBUG=true) ---
23
+ # LOGODEV_MCP_DEBUG_PORT=5678
24
+ # LOGODEV_MCP_DEBUG_WAIT=false # set true to block startup until the IDE attaches
25
+
26
+ # --- Domain (populate from your ProjectConfig) ---
27
+ # logo.dev publishable key (pk_…) — enables the get_logo tool
28
+ # LOGODEV_MCP_PUBLISHABLE_KEY=pk_live_xxx
29
+ # logo.dev secret key (sk_…) — enables search_brands / describe_company / get_brand
30
+ # LOGODEV_MCP_SECRET_KEY=sk_live_xxx
@@ -0,0 +1,18 @@
1
+ # Gemini Code Assist — repo review config
2
+ # Reference: https://developers.google.com/gemini-code-assist/docs/customize-repo-review
3
+ #
4
+ # gemini-code-assist is a merge gate, not a pair reviewer. Local review (two
5
+ # subagent code-reviewers with different prompt templates) runs before any
6
+ # push; by the time the PR opens we expect the hosted bot to have nothing to
7
+ # flag. These settings narrow the bot's scope so it fires on flip-to-ready
8
+ # (not on every draft push) and only surfaces real issues.
9
+
10
+ code_review:
11
+ disable: false
12
+ comment_severity_threshold: HIGH
13
+ max_review_comments: 20
14
+ pull_request_opened:
15
+ help: false
16
+ summary: false
17
+ code_review: true
18
+ include_drafts: false
@@ -0,0 +1,3 @@
1
+ # Generated by scripts/vendor_spa.py — do not edit directly.
2
+ # Edit static/app.src.html instead and re-run the vendor script.
3
+ src/logodev_mcp/static/app.html linguist-generated=true
@@ -0,0 +1,7 @@
1
+ name: "CodeQL config"
2
+
3
+ query-filters:
4
+ - exclude:
5
+ id: py/clear-text-storage-of-sensitive-information
6
+ paths:
7
+ - src/logodev_mcp/git.py
@@ -0,0 +1,15 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: pip
4
+ directory: "/"
5
+ schedule:
6
+ interval: weekly
7
+ labels:
8
+ - dependencies
9
+
10
+ - package-ecosystem: github-actions
11
+ directory: "/"
12
+ schedule:
13
+ interval: weekly
14
+ labels:
15
+ - dependencies
@@ -0,0 +1,332 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+ workflow_dispatch:
9
+
10
+ jobs:
11
+ lint:
12
+ name: Lint
13
+ runs-on: ubuntu-latest
14
+ timeout-minutes: 10
15
+ steps:
16
+ - uses: actions/checkout@v7
17
+
18
+ - name: Install uv
19
+ uses: astral-sh/setup-uv@v8.2.0
20
+ with:
21
+ version: "latest"
22
+
23
+ - name: Cache Python interpreter
24
+ uses: actions/cache@v5
25
+ with:
26
+ path: ~/.local/share/uv/python
27
+ key: uv-python-3.12-${{ runner.os }}
28
+
29
+ - name: Set up Python
30
+ run: uv python install 3.12
31
+
32
+ - name: Install dependencies
33
+ run: uv sync --all-extras --all-groups
34
+
35
+ - name: Run ruff check
36
+ run: uv run ruff check src/ tests/
37
+
38
+ - name: Run ruff format check
39
+ run: uv run ruff format --check src/ tests/
40
+
41
+ typecheck:
42
+ name: Type Check
43
+ runs-on: ubuntu-latest
44
+ timeout-minutes: 10
45
+ steps:
46
+ - uses: actions/checkout@v7
47
+
48
+ - name: Install uv
49
+ uses: astral-sh/setup-uv@v8.2.0
50
+ with:
51
+ version: "latest"
52
+
53
+ - name: Cache Python interpreter
54
+ uses: actions/cache@v5
55
+ with:
56
+ path: ~/.local/share/uv/python
57
+ key: uv-python-3.12-${{ runner.os }}
58
+
59
+ - name: Set up Python
60
+ run: uv python install 3.12
61
+
62
+ - name: Install dependencies
63
+ run: uv sync --all-extras --all-groups
64
+
65
+ - name: Run mypy
66
+ run: uv run mypy src/ tests/
67
+
68
+ test:
69
+ name: Test (Python ${{ matrix.python-version }})
70
+ runs-on: ubuntu-latest
71
+ # Prevent a stalled `uv python install` from blocking the PR for hours.
72
+ # 20 min covers the full test matrix with headroom; cold interpreter
73
+ # downloads from python-build-standalone are the most likely stall source.
74
+ timeout-minutes: 20
75
+ continue-on-error: ${{ matrix.experimental || false }}
76
+ permissions:
77
+ contents: read
78
+ statuses: write
79
+ strategy:
80
+ fail-fast: false
81
+ matrix:
82
+ include:
83
+ - python-version: "3.11"
84
+ experimental: false
85
+ - python-version: "3.12"
86
+ experimental: false
87
+ - python-version: "3.13"
88
+ experimental: false
89
+ - python-version: "3.14"
90
+ experimental: true
91
+ steps:
92
+ - uses: actions/checkout@v7
93
+
94
+ - name: Install uv
95
+ uses: astral-sh/setup-uv@v8.2.0
96
+ with:
97
+ version: "latest"
98
+
99
+ - name: Cache Python interpreter
100
+ uses: actions/cache@v5
101
+ with:
102
+ # `uv python install` writes to UV_PYTHON_INSTALL_DIR, which is
103
+ # separate from the uv package cache and not covered by setup-uv's
104
+ # enable-cache. Caching by version + OS avoids re-downloading the
105
+ # python-build-standalone tarball on every run.
106
+ path: ~/.local/share/uv/python
107
+ key: uv-python-${{ matrix.python-version }}-${{ runner.os }}
108
+
109
+ - name: Set up Python ${{ matrix.python-version }}
110
+ run: uv python install ${{ matrix.python-version }}
111
+
112
+ - name: Install dependencies
113
+ run: uv sync --all-extras --all-groups
114
+
115
+ - name: Run tests with coverage
116
+ run: uv run pytest --cov --cov-report=xml
117
+
118
+ - name: Upload coverage to Codecov
119
+ if: matrix.python-version == '3.13'
120
+ uses: codecov/codecov-action@v6
121
+ with:
122
+ files: ./coverage.xml
123
+ fail_ci_if_error: false
124
+ override_pr: ${{ github.event.pull_request.number }}
125
+ env:
126
+ CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
127
+
128
+ - name: Fetch base branch for diff-cover
129
+ if: matrix.python-version == '3.13' && github.event_name == 'pull_request'
130
+ run: git fetch origin ${{ github.base_ref }} --depth=50
131
+
132
+ - name: Check patch coverage
133
+ id: diffcover
134
+ if: matrix.python-version == '3.13' && github.event_name == 'pull_request'
135
+ env:
136
+ BASE_REF: ${{ github.base_ref }}
137
+ run: |
138
+ # Check if PR has Python source changes
139
+ HAS_PY=$(git diff --name-only "origin/${BASE_REF}...HEAD" | grep -c '\.py$' || true)
140
+ if [ "$HAS_PY" -eq 0 ]; then
141
+ echo "state=success" >> "$GITHUB_OUTPUT"
142
+ echo "description=Coverage not affected" >> "$GITHUB_OUTPUT"
143
+ echo "No Python source changes — skipping diff-cover"
144
+ else
145
+ OUTPUT=$(uv run diff-cover coverage.xml --compare-branch="origin/${BASE_REF}" --fail-under=80 2>&1) && RC=0 || RC=$?
146
+ echo "$OUTPUT"
147
+ TOTAL=$(echo "$OUTPUT" | grep -oP 'Total:\s+\K[\d.]+' || true)
148
+ if [ -z "$TOTAL" ] && [ "$RC" -ne 0 ]; then
149
+ echo "state=error" >> "$GITHUB_OUTPUT"
150
+ echo "description=diff-cover failed to compute patch coverage" >> "$GITHUB_OUTPUT"
151
+ elif [ -z "$TOTAL" ]; then
152
+ echo "state=success" >> "$GITHUB_OUTPUT"
153
+ echo "description=No coverable lines in diff" >> "$GITHUB_OUTPUT"
154
+ elif [ "$RC" -eq 0 ]; then
155
+ echo "state=success" >> "$GITHUB_OUTPUT"
156
+ echo "description=Patch coverage: ${TOTAL}%" >> "$GITHUB_OUTPUT"
157
+ else
158
+ echo "state=failure" >> "$GITHUB_OUTPUT"
159
+ echo "description=Patch coverage: ${TOTAL}% (minimum 80%)" >> "$GITHUB_OUTPUT"
160
+ fi
161
+ fi
162
+
163
+ - name: Save patch coverage result
164
+ if: matrix.python-version == '3.13' && github.event_name == 'pull_request'
165
+ env:
166
+ PATCH_STATE: ${{ steps.diffcover.outputs.state || 'error' }}
167
+ PATCH_DESC: ${{ steps.diffcover.outputs.description || 'diff-cover step did not run' }}
168
+ run: |
169
+ jq -n --arg state "$PATCH_STATE" --arg description "$PATCH_DESC" \
170
+ '{"state":$state,"description":$description}' > patch-coverage.json
171
+
172
+ - name: Upload patch coverage artifact
173
+ if: matrix.python-version == '3.13' && github.event_name == 'pull_request'
174
+ uses: actions/upload-artifact@v7
175
+ with:
176
+ name: patch-coverage
177
+ path: patch-coverage.json
178
+ retention-days: 1
179
+
180
+ - name: Post codecov/patch status
181
+ # Fork PRs: GITHUB_TOKEN is read-only for pull_request events from forks regardless
182
+ # of the permissions block — GitHub security restriction. continue-on-error prevents
183
+ # the job from failing; coverage-status.yml posts the status via workflow_run instead.
184
+ if: matrix.python-version == '3.13' && github.event_name == 'pull_request' && always()
185
+ continue-on-error: true
186
+ uses: actions/github-script@v9
187
+ env:
188
+ PATCH_STATE: ${{ steps.diffcover.outputs.state }}
189
+ PATCH_DESC: ${{ steps.diffcover.outputs.description }}
190
+ with:
191
+ github-token: ${{ secrets.GITHUB_TOKEN }}
192
+ script: |
193
+ const state = process.env.PATCH_STATE || 'error';
194
+ const description = process.env.PATCH_DESC || 'diff-cover step did not run';
195
+ const headSha = context.payload.pull_request.head.sha;
196
+ core.info(`Posting codecov/patch: ${state} — ${description} to ${headSha}`);
197
+ await github.rest.repos.createCommitStatus({
198
+ owner: context.repo.owner,
199
+ repo: context.repo.repo,
200
+ sha: headSha,
201
+ state,
202
+ context: 'codecov/patch',
203
+ description,
204
+ target_url: 'https://app.codecov.io/gh/pvliesdonk/logodev-mcp',
205
+ });
206
+
207
+ audit:
208
+ name: Dependency Audit
209
+ runs-on: ubuntu-latest
210
+ timeout-minutes: 10
211
+ permissions:
212
+ contents: read
213
+ steps:
214
+ - uses: actions/checkout@v7
215
+
216
+ - name: Install uv
217
+ uses: astral-sh/setup-uv@v8.2.0
218
+ with:
219
+ version: "latest"
220
+
221
+ - name: Cache Python interpreter
222
+ uses: actions/cache@v5
223
+ with:
224
+ path: ~/.local/share/uv/python
225
+ key: uv-python-3.12-${{ runner.os }}
226
+
227
+ - name: Set up Python
228
+ run: uv python install 3.12
229
+
230
+ - name: Export dependency list (excluding local project)
231
+ # `dev` is uv's only auto-activated default group, so --no-default-groups
232
+ # excludes it; `docs` is non-default and never exported unless explicitly
233
+ # requested via --group/--all-groups (neither passed here). Net effect:
234
+ # only runtime + user-defined extras land in the audit input — avoids
235
+ # spurious CVE reports against tooling (pip-audit's own `pip` dep, etc.)
236
+ # that does not run in production.
237
+ run: uv export --all-extras --no-default-groups --frozen --no-emit-project --no-hashes -o ${{ runner.temp }}/requirements.txt
238
+
239
+ - name: Run pip-audit
240
+ run: |
241
+ uvx pip-audit --strict --progress-spinner off \
242
+ --ignore-vuln CVE-2026-42561 \
243
+ -r ${{ runner.temp }}/requirements.txt
244
+ # CVE-2026-42561: python-multipart <0.0.27, pulled in transitively by
245
+ # fastmcp/starlette. Ignored until the upstream pin chain propagates
246
+ # the fix to 0.0.27. Remove once `uv lock` resolves >=0.0.27.
247
+
248
+ secrets:
249
+ name: Secret Detection
250
+ runs-on: ubuntu-latest
251
+ permissions:
252
+ contents: read
253
+ steps:
254
+ - uses: actions/checkout@v7
255
+ with:
256
+ fetch-depth: 0
257
+
258
+ - name: Run gitleaks
259
+ uses: gitleaks/gitleaks-action@ff98106e4c7b2bc287b24eaf42907196329070c7 # v2
260
+ env:
261
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
262
+
263
+ vale:
264
+ name: Docs Prose (Vale)
265
+ runs-on: ubuntu-latest
266
+ permissions:
267
+ contents: read
268
+ # vale-cli/vale-action posts findings as PR annotations via reviewdog.
269
+ # The default reporter (`github-pr-annotations`) uses the GitHub Checks
270
+ # API — `checks: write` is sufficient. If a downstream switches the
271
+ # reporter to `github-pr-review` (inline PR review comments), they
272
+ # need to add `pull-requests: write` here too.
273
+ checks: write
274
+ steps:
275
+ - uses: actions/checkout@v7
276
+
277
+ - name: Cache Vale style packages
278
+ # Cache only the downloaded pack directories — NOT .vale/styles/config/.
279
+ # The config/ subtree (accept.txt vocabulary) is tracked by git and must
280
+ # stay authoritative from checkout. Caching the whole .vale/styles tree
281
+ # would let restore-keys overwrite a newly-added vocab term with the
282
+ # stale snapshot on the exact PR that adds the term.
283
+ # Pack list mirrors the Packages = line in .vale.ini; if you add or
284
+ # remove a pack, update both. Bump the v1- prefix to evict all cached
285
+ # packs if Vale changes pack format backward-incompatibly.
286
+ uses: actions/cache@v5
287
+ with:
288
+ path: |
289
+ .vale/styles/Google
290
+ .vale/styles/proselint
291
+ .vale/styles/write-good
292
+ .vale/styles/ai-tells
293
+ key: vale-styles-v1-${{ hashFiles('.vale.ini') }}
294
+ # Warm-start fallback: restores the most recent pack snapshot when
295
+ # .vale.ini changes (e.g. URL bump). vale sync then only re-fetches
296
+ # the changed pack rather than re-downloading all four.
297
+ restore-keys: vale-styles-v1-
298
+
299
+ - name: Run Vale
300
+ # SHA pin matches the gitleaks-action pattern earlier in this file.
301
+ # The current release is named "v2.1.2" in the GitHub UI but the
302
+ # underlying git tag is `2.1.2` (no `v` prefix) — pinning to the
303
+ # SHA sidesteps that mismatch and provides supply-chain hygiene.
304
+ uses: vale-cli/vale-action@85f9f7f2c5f449ac0ae5b66662961bae3f77ca6a # v2.1.2
305
+ with:
306
+ # Pin Vale CLI version explicitly. Bump in lockstep with the
307
+ # pre-commit hook `rev:` in .pre-commit-config.yaml — template-ci
308
+ # asserts the two stay synchronized.
309
+ version: "3.14.2"
310
+ files: docs
311
+ # Working specs follow internal conventions, not user-facing prose
312
+ # style — exclude from linting. NO inner single quotes around the
313
+ # glob value: vale-action splits `vale_flags` on whitespace and
314
+ # passes argv elements directly (no shell), so literal quotes here
315
+ # would be passed through to Vale, the glob would match no files,
316
+ # and CI would silently exit 0. Verified empirically.
317
+ vale_flags: "--glob=!docs/superpowers/**"
318
+ # Failure gating is controlled by MinAlertLevel = error in
319
+ # .vale.ini (governs both what Vale prints AND its exit code)
320
+ # combined with fail_on_error below — only error-severity
321
+ # findings fail CI; warnings and suggestions surface as advisory
322
+ # annotations. (The action also accepts a `level:` input, but at
323
+ # the pinned SHA that input is declared but never read — the
324
+ # reviewdog level is derived from Vale's exit code and
325
+ # fail_on_error. Setting it here would be a no-op.)
326
+ fail_on_error: true
327
+ # filter_mode defaults to `added` — only findings on lines this PR
328
+ # adds or modifies fail the build. Pre-existing prose debt isn't a
329
+ # blocker for new contributions; downstream's own untouched docs
330
+ # don't gate PRs that don't touch them. To enforce repo-wide
331
+ # cleanliness, set this to `nofilter`.
332
+ filter_mode: added
@@ -0,0 +1,58 @@
1
+ name: Claude Code Review
2
+
3
+ on:
4
+ pull_request:
5
+ types: [opened, synchronize, ready_for_review, reopened]
6
+ # Optional: Only run on specific file changes
7
+ # paths:
8
+ # - "src/**/*.ts"
9
+ # - "src/**/*.tsx"
10
+ # - "src/**/*.js"
11
+ # - "src/**/*.jsx"
12
+
13
+ jobs:
14
+ claude-review:
15
+ # Skip PRs from forks: GitHub does not expose repository secrets
16
+ # (including CLAUDE_CODE_OAUTH_TOKEN) to workflows running in fork-PR
17
+ # context, regardless of maintainer approval. Running anyway produces
18
+ # a hard-failing check on every external contribution. Maintainers who
19
+ # want a bot review on a fork PR can push the contributor's branch to
20
+ # this repo under a topic name and the workflow will run.
21
+ if: github.event.pull_request.head.repo.full_name == github.repository
22
+
23
+ # Optional: Filter by PR author
24
+ # if: |
25
+ # github.event.pull_request.user.login == 'external-contributor' ||
26
+ # github.event.pull_request.user.login == 'new-developer' ||
27
+ # github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR'
28
+
29
+ runs-on: ubuntu-latest
30
+ permissions:
31
+ contents: read
32
+ pull-requests: write # Required so the review action can post inline comments
33
+ issues: read
34
+ id-token: write
35
+
36
+ steps:
37
+ - name: Checkout repository
38
+ uses: actions/checkout@v7
39
+ with:
40
+ fetch-depth: 1
41
+
42
+ - name: Run Claude Code Review
43
+ id: claude-review
44
+ uses: anthropics/claude-code-action@v1
45
+ with:
46
+ claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
47
+ plugin_marketplaces: 'https://github.com/anthropics/claude-code.git'
48
+ plugins: 'code-review@claude-code-plugins'
49
+ # `--comment` tells the plugin to actually post (without it, the plugin
50
+ # runs the full review and stops silently — burning ~$3/PR for no output).
51
+ prompt: '/code-review:code-review --comment ${{ github.repository }}/pull/${{ github.event.pull_request.number }}'
52
+ # Surface progress so a silent failure is visible: a sticky tracking
53
+ # comment updates during the run, and the Claude Code Report appears
54
+ # in the job's GitHub Step Summary.
55
+ track_progress: true
56
+ display_report: true
57
+ # See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
58
+ # or https://code.claude.com/docs/en/cli-reference for available options
@@ -0,0 +1,55 @@
1
+ name: Claude Code
2
+
3
+ on:
4
+ issue_comment:
5
+ types: [created]
6
+ pull_request_review_comment:
7
+ types: [created]
8
+ issues:
9
+ types: [opened, assigned]
10
+ pull_request_review:
11
+ types: [submitted]
12
+
13
+ jobs:
14
+ claude:
15
+ # Trigger only on @claude mentions, AND on the two PR-context events
16
+ # (`pull_request_review*`) only when the PR head is in this repo. Those
17
+ # events run in PR context for fork PRs, where GitHub withholds repository
18
+ # secrets (incl. CLAUDE_CODE_OAUTH_TOKEN) and the action would auth-fail.
19
+ # `issues` and `issue_comment` always run in base-repo context, so secrets
20
+ # are available — no fork check needed there.
21
+ if: |
22
+ (github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
23
+ (github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude'))) ||
24
+ (github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude') && github.event.pull_request.head.repo.full_name == github.repository) ||
25
+ (github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude') && github.event.pull_request.head.repo.full_name == github.repository)
26
+ runs-on: ubuntu-latest
27
+ permissions:
28
+ contents: read
29
+ pull-requests: read
30
+ issues: read
31
+ id-token: write
32
+ actions: read # Required for Claude to read CI results on PRs
33
+ steps:
34
+ - name: Checkout repository
35
+ uses: actions/checkout@v7
36
+ with:
37
+ fetch-depth: 1
38
+
39
+ - name: Run Claude Code
40
+ id: claude
41
+ uses: anthropics/claude-code-action@v1
42
+ with:
43
+ claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
44
+
45
+ # This is an optional setting that allows Claude to read CI results on PRs
46
+ additional_permissions: |
47
+ actions: read
48
+
49
+ # Optional: Give a custom prompt to Claude. If this is not specified, Claude will perform the instructions specified in the comment that tagged it.
50
+ # prompt: 'Update the pull request description to include a summary of changes.'
51
+
52
+ # Optional: Add claude_args to customize behavior and configuration
53
+ # See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
54
+ # or https://code.claude.com/docs/en/cli-reference for available options
55
+ # claude_args: '--allowed-tools Bash(gh pr *)'
@@ -0,0 +1,31 @@
1
+ name: CodeQL
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+ schedule:
9
+ - cron: "0 6 * * 1" # Weekly on Monday at 06:00 UTC
10
+
11
+ permissions:
12
+ actions: read
13
+ contents: read
14
+ security-events: write
15
+
16
+ jobs:
17
+ analyze:
18
+ name: CodeQL Analysis
19
+ runs-on: ubuntu-latest
20
+ steps:
21
+ - uses: actions/checkout@v7
22
+
23
+ - name: Initialize CodeQL
24
+ uses: github/codeql-action/init@v4
25
+ with:
26
+ languages: python
27
+ queries: security-extended
28
+ config-file: .github/codeql/codeql-config.yml
29
+
30
+ - name: Perform CodeQL Analysis
31
+ uses: github/codeql-action/analyze@v4