Skip to content

Commit 0b5e838

Browse files
committed
pull in
1 parent 5bbd179 commit 0b5e838

20 files changed

Lines changed: 231 additions & 119 deletions

File tree

‎.claude/settings/permissions/bash.jsonc‎

Lines changed: 51 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,63 @@
4444
// Git & Version Control
4545
"Bash(git add *)",
4646
"Bash(git branch *)",
47+
"Bash(git checkout *)",
4748
"Bash(git commit *)",
4849
"Bash(git diff *)",
4950
"Bash(git log *)",
51+
"Bash(git mv *)",
5052
"Bash(git push)",
5153
"Bash(git remote get-url origin)",
5254
"Bash(git rev-parse *)",
5355
"Bash(git status *)",
56+
// Github
57+
"Bash(gh issue list *)",
58+
"Bash(gh issue view *)",
59+
"Bash(gh run download *)",
60+
"Bash(gh run list *)",
61+
"Bash(gh run view *)",
62+
"Bash(gh run watch *)",
63+
"Bash(gh search *)",
64+
"Bash(gh pr view *)",
65+
"Bash(gh pr diff *)",
66+
// Local app interaction
67+
// Claude currently has terrible support for this: https://github.com/anthropics/claude-code/issues/338 using `:*` as a pattern is not allowed (doesn't error, just doesn't really work), so have to specify _something_ between the colon and asterisk.
68+
"Bash(curl http://localhost:1*)",
69+
"Bash(curl http://localhost:2*)",
70+
"Bash(curl http://localhost:3*)",
71+
"Bash(curl http://localhost:4*)",
72+
"Bash(curl http://localhost:5*)",
73+
"Bash(curl http://localhost:6*)",
74+
"Bash(curl http://localhost:7*)",
75+
"Bash(curl http://localhost:8*)",
76+
"Bash(curl http://localhost:9*)",
77+
"Bash(curl -s http://localhost:1*)",
78+
"Bash(curl -s http://localhost:2*)",
79+
"Bash(curl -s http://localhost:3*)",
80+
"Bash(curl -s http://localhost:4*)",
81+
"Bash(curl -s http://localhost:5*)",
82+
"Bash(curl -s http://localhost:6*)",
83+
"Bash(curl -s http://localhost:7*)",
84+
"Bash(curl -s http://localhost:8*)",
85+
"Bash(curl -s http://localhost:9*)",
86+
"Bash(curl \"http://localhost:1*)",
87+
"Bash(curl \"http://localhost:2*)",
88+
"Bash(curl \"http://localhost:3*)",
89+
"Bash(curl \"http://localhost:4*)",
90+
"Bash(curl \"http://localhost:5*)",
91+
"Bash(curl \"http://localhost:6*)",
92+
"Bash(curl \"http://localhost:7*)",
93+
"Bash(curl \"http://localhost:8*)",
94+
"Bash(curl \"http://localhost:9*)",
95+
"Bash(curl -s \"http://localhost:1*)",
96+
"Bash(curl -s \"http://localhost:2*)",
97+
"Bash(curl -s \"http://localhost:3*)",
98+
"Bash(curl -s \"http://localhost:4*)",
99+
"Bash(curl -s \"http://localhost:5*)",
100+
"Bash(curl -s \"http://localhost:6*)",
101+
"Bash(curl -s \"http://localhost:7*)",
102+
"Bash(curl -s \"http://localhost:8*)",
103+
"Bash(curl -s \"http://localhost:9*)",
54104
// Misc
55105
"Bash(amp *)",
56106
"Bash(atuin *)",
@@ -64,8 +114,7 @@
64114
"Bash(zk *)",
65115
// Node.js
66116
"Bash(pnpm list *)",
67-
"Bash(pnpm test-unit *)",
68-
"Bash(pnpm test-e2e *)",
117+
"Bash(pnpm test*)",
69118
"Bash(pnpm view *)",
70119
// Python
71120
"Bash(uv run pytest *)",
@@ -83,10 +132,6 @@
83132
// Search
84133
"Bash(rg *)",
85134
// Research
86-
"Bash(gh issue list *)",
87-
"Bash(gh search *)",
88-
"Bash(gh pr view *)",
89-
"Bash(gh pr diff *)",
90135
],
91136
"ask": [
92137
// let's hold off before we let it use the github CLI in any free running allow mode...I don't want it somehow approving PRs with the user's credentials
@@ -95,11 +140,7 @@
95140
"Bash(gh secret *)",
96141
"Bash(gh ruleset *)",
97142
"Bash(aws *)", // let's hold off before we let it use AWS CLI in any free running allow mode. We need to be very sure we don't have any access to staging or production credentials in our dev environment (...which we shouldn't...but we need to double check that or consider any other safeguards first)
98-
"Bash(curl *)",
99-
"Bash(ln *)",
100143
"WebFetch",
101-
// Git & Version Control
102-
"Bash(git reset --hard *)",
103144
],
104145
"deny": [
105146
// Exceptions to generally allowed AI tooling

‎.copier-answers.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Changes here will be overwritten by Copier
2-
_commit: v0.0.126
2+
_commit: v0.0.130
33
_src_path: gh:LabAutomationAndScreening/copier-base-template.git
44
copier_answers_directory: .
55
description: Copier template for creating Python libraries and executables

‎.devcontainer/devcontainer.json‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
"optimize": true
1515
},
1616
// https://github.com/anthropics/devcontainer-features/blob/main/src/claude-code/devcontainer-feature.json
17-
"ghcr.io/anthropics/devcontainer-features/claude-code:1.0.5": {}
17+
"ghcr.io/anthropics/devcontainer-features/claude-code:1.0.5": {},
1818
},
1919
"customizations": {
2020
"vscode": {
@@ -27,13 +27,13 @@
2727
"MS-vsliveshare.vsliveshare@1.0.5905",
2828
"github.copilot@1.388.0",
2929
"github.copilot-chat@0.44.2",
30-
"anthropic.claude-code@2.1.143",
30+
"anthropic.claude-code@2.1.145",
3131

3232
// Python
3333
"ms-python.python@2026.5.2026032701",
3434
"ms-python.vscode-pylance@2026.2.100",
3535
"ms-vscode-remote.remote-containers@0.414.0",
36-
"charliermarsh.ruff@2026.40.0",
36+
"charliermarsh.ruff@2026.44.0",
3737

3838
// Misc file formats
3939
"bierner.markdown-mermaid@1.29.0",
@@ -65,5 +65,5 @@
6565
"initializeCommand": "sh .devcontainer/initialize-command.sh",
6666
"onCreateCommand": "sh .devcontainer/on-create-command.sh",
6767
"postStartCommand": "sh .devcontainer/post-start-command.sh"
68-
// Devcontainer context hash (do not manually edit this, it's managed by a pre-commit hook): 06e5a5c0 # spellchecker:disable-line
68+
// Devcontainer context hash (do not manually edit this, it's managed by a pre-commit hook): ca20b755 # spellchecker:disable-line
6969
}

‎.devcontainer/install-ci-tooling.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
import tempfile
88
from pathlib import Path
99

10-
UV_VERSION = "0.11.14"
11-
PNPM_VERSION = "11.2.2"
10+
UV_VERSION = "0.11.17"
11+
PNPM_VERSION = "11.5.0"
1212
COPIER_VERSION = "==9.15.1"
1313
COPIER_TEMPLATE_EXTENSIONS_VERSION = "==0.3.3"
1414
PRE_COMMIT_VERSION = "4.5.1"

‎.gitignore‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,10 @@ docs/_build
6868
tests/**/snapshots/*_actual.png
6969
tests/**/snapshots/*_diff.png
7070
pytest.log
71+
test-screenshots/
72+
playwright-report/
73+
test-results/
74+
.vitest-attachments/
7175

7276
# test coverage
7377
tests/__coverage__
@@ -83,6 +87,8 @@ prof/
8387
# NodeJS
8488
node_modules/
8589
.pnpm-store/
90+
# TypeScript incremental build cache
91+
*.tsbuildinfo
8692

8793

8894
# Nuxt

‎AGENTS.md‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,12 @@ This project is a Copier template used to generate other copier templates. It is
1414
- Prefer keyword-only parameters (unless a very clear single-argument function): use `*` in Python signatures and destructured options objects in TypeScript.
1515
- When disabling a linting rule with an inline directive, provide a comment at the end of the line (or on the line above for tools that don't allow extra text after an inline directive) describing the reasoning for disabling the rule.
1616
- Avoid telling the type checker what a type is rather than letting it prove it. This includes type assertions (`as SomeType` in TypeScript, `cast()` in Python) and variable annotations that override inference. Prefer approaches that let the type checker verify the type itself: `isinstance`/`instanceof` narrowing, restructuring code so the correct type flows naturally, or using discriminated unions. When there is genuinely no alternative, add a comment explaining why the workaround is necessary and why it is safe.
17+
- Avoid `||` (TypeScript) or `or` (Python) in `if`/`elif` conditions, and avoid `x in ['a', 'b']`-style membership tests in implementation code — coverage tools treat these as a single branch, silently masking untested paths and producing false 100% branch coverage. Use separate `if`/`elif` branches instead so each condition is independently covered.
1718

1819
## Testing
1920

2021
- Always run tests with an explicit path (e.g. uv run pytest tests/unit) — test runners discover all types (unit, integration, E2E...) by default.
21-
- When iterating on a single test, run that test in isolation first and confirm it is in the expected state (red or green) before widening to the full suite. Use the most targeted invocation available: a specific test function for Python (e.g. `uv run pytest path/to/test.py::test_name --no-cov`) or a file path and name filter for TypeScript (e.g. `pnpm test-unit -- path/to/test.spec.ts -t "test name" --no-coverage`). Only run the full suite once the target test behaves as expected.
22+
- When iterating on a single test, run that test in isolation first and confirm it is in the expected state (red or green) before widening to the full suite. Use the most targeted invocation available: a specific test function for Python (e.g. `uv run pytest path/to/test.py::test_name --no-cov`) or a file path and name filter for TypeScript (e.g. `pnpm test-unit path/to/test.spec.ts -t "test name" --no-coverage`). Only run the full suite once the target test behaves as expected.
2223
- Test coverage requirements are usually at 100%, so when running a subset of tests, always disable test coverage to avoid the test run failing for insufficient coverage.
2324
- Avoid magic values in comparisons in tests in all languages (like ruff rule PLR2004 specifies). Note: `1` and `0` are not magic numbers (according to PLR2004)
2425
- Prefer using random values in tests rather than arbitrary ones (e.g. the faker library, uuids, random.randint) when possible. For enums, pick randomly rather than hardcoding one value.

‎copier.yml‎

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ create_docs:
126126
help: Do you want to create documentation for this project?
127127
default: yes
128128

129-
is_frozen_executable:
129+
deploy_as_executable:
130130
type: bool
131131
help: Is this project a frozen executable (instead of a PyPI-compatible library)?
132132
default: no
@@ -135,7 +135,7 @@ use_windows_in_exe_ci:
135135
type: bool
136136
help: Should CI in the instantiated template also use Windows runners for building and testing the executable?
137137
default: no
138-
when: is_frozen_executable
138+
when: deploy_as_executable
139139

140140
use_codecov:
141141
type: bool
@@ -158,14 +158,23 @@ _tasks:
158158
--target-file .pre-commit-config.yaml
159159
when: "{{ not install_claude_cli }}"
160160
# Copier does not preserve executable permissions when instantiating the template, so we set them explicitly here.
161+
# git update-index is also needed because with core.fileMode=false (common on WSL2) git ignores the on-disk exec bit,
162+
# so a plain `git add` would not capture it. It is guarded on the file being tracked, since on an initial `copier copy`
163+
# into a fresh repo the file is not in the index yet (the chmod alone covers that case).
161164
- command: |
162165
if [ -f scripts/delete_false_positive_rej.py ]; then
163166
chmod +x scripts/delete_false_positive_rej.py
167+
if git ls-files --error-unmatch scripts/delete_false_positive_rej.py > /dev/null 2>&1; then
168+
git update-index --chmod=+x scripts/delete_false_positive_rej.py
169+
fi
164170
fi
165171
- command: |
166172
for script in .claude/skills/address-pr-comments/check-footer.py .claude/skills/address-pr-comments/fetch-pr-comments.py .claude/skills/address-pr-comments/post-reply.py; do
167173
if [ -f "$script" ]; then
168174
chmod +x "$script"
175+
if git ls-files --error-unmatch "$script" > /dev/null 2>&1; then
176+
git update-index --chmod=+x "$script"
177+
fi
169178
fi
170179
done
171180
- command: |

‎extensions/context.py‎

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,16 @@ class ContextUpdater(ContextHook):
1212
def hook( # noqa: PLR0915 # yes, this is a lot of statements, but it's all just creating the dict
1313
self, context: dict[Any, Any]
1414
) -> dict[Any, Any]:
15-
context["uv_version"] = "0.11.14"
16-
context["pnpm_version"] = "11.2.2"
15+
context["uv_version"] = "0.11.17"
16+
context["pnpm_version"] = "11.5.0"
1717
context["npm_version"] = "11.13.0"
1818
context["nvm_version"] = "0.40.4"
1919
context["pre_commit_version"] = "4.5.1"
2020
context["pyright_version"] = ">=1.1.409"
2121
context["pytest_version"] = ">=9.0.3"
2222
context["pytest_randomly_version"] = ">=4.1.0"
2323
context["pytest_cov_version"] = ">=7.1.0"
24-
context["ty_version"] = ">=0.0.38"
24+
context["ty_version"] = ">=0.0.40"
2525
context["copier_version"] = "==9.15.1"
2626
context["copier_template_extensions_version"] = "==0.3.3"
2727
context["sphinx_version"] = "9.0.4"
@@ -37,44 +37,45 @@ def hook( # noqa: PLR0915 # yes, this is a lot of statements, but it's all just
3737
context["pyinstaller_version"] = ">=6.20.0"
3838
context["setuptools_version"] = "80.7.1"
3939
context["strawberry_graphql_version"] = ">=0.298.0"
40-
context["fastapi_version"] = ">=0.136.1"
40+
context["fastapi_version"] = ">=0.136.3"
4141
context["fastapi_offline_version"] = ">=1.7.4"
42-
context["uvicorn_version"] = ">=0.47.0"
42+
context["uvicorn_version"] = ">=0.48.0"
4343
context["lab_auto_pulumi_version"] = ">=0.2.0"
4444
context["ariadne_codegen_version"] = ">=0.18.0"
4545
context["pytest_mock_version"] = ">=3.15.1"
4646
context["uuid_utils_version"] = ">=0.16.0"
4747
context["syrupy_version"] = ">=5.2.0"
4848
context["structlog_version"] = ">=25.5.0"
4949
context["httpx_version"] = ">=0.28.1"
50-
context["python_kiota_bundle_version"] = ">=1.10.1"
50+
context["httpx2_version"] = ">=2.2.0"
51+
context["python_kiota_bundle_version"] = ">=1.10.2"
5152
context["vcrpy_version"] = ">=8.1.1"
5253
context["pytest_recording_version"] = ">=0.13.4"
53-
context["pytest_asyncio_version"] = ">=1.3.0"
54+
context["pytest_asyncio_version"] = ">=1.4.0"
55+
context["pytest_timeout_version"] = ">=2.4.0"
5456
context["pytest_reserial_version"] = ">=0.6.1"
5557
context["python_faker_version"] = ">=40.18.0"
5658

5759
context["default_node_version"] = "24.11.1"
58-
context["nuxt_ui_version"] = "^4.7.1"
59-
context["nuxt_version"] = "^4.4.5"
60+
context["nuxt_ui_version"] = "^4.8.1"
61+
context["nuxt_version"] = "^4.4.6"
6062
context["nuxt_icon_version"] = "^2.2.1"
61-
context["typescript_version"] = "^5.9.3"
63+
context["typescript_version"] = "^6.0.2"
6264
context["playwright_version"] = "^1.60.0"
6365
context["vue_version"] = "^3.5.30"
64-
context["vue_tsc_version"] = "^3.3.0"
66+
context["vue_tsc_version"] = "^3.3.2"
6567
context["vue_devtools_api_version"] = "^8.1.0"
66-
context["vue_router_version"] = "^5.0.3"
68+
context["vue_router_version"] = "^5.1.0"
6769
context["dotenv_cli_version"] = "^11.0.0"
6870
context["faker_version"] = "^10.4.0"
69-
context["vitest_version"] = "^4.1.6"
71+
context["vitest_version"] = "^4.1.7"
7072
context["vitest_eslint_plugin_version"] = "^1.6.17"
7173
context["eslint_version"] = "^10.4.0"
7274
context["nuxt_eslint_version"] = "^1.15.1"
7375
context["zod_version"] = "^4.3.6"
7476
context["zod_from_json_schema_version"] = "^0.5.1"
7577
context["nuxt_apollo_version"] = "5.0.0-alpha.15"
7678
context["graphql_codegen_cli_version"] = "^6.3.0"
77-
context["graphql_codegen_typescript_version"] = "^5.0.7"
7879
context["graphql_tools_mock_version"] = "^9.1.0"
7980
context["tailwindcss_version"] = "^4.2.0"
8081
context["iconify_vue_version"] = "^5.0.0"
@@ -85,7 +86,7 @@ def hook( # noqa: PLR0915 # yes, this is a lot of statements, but it's all just
8586
context["nuxt_test_utils_version"] = "^4.0.3"
8687
context["vue_eslint_parser_version"] = "^10.4.0"
8788
context["happy_dom_version"] = "^20.9.0"
88-
context["node_kiota_bundle_version"] = "1.0.0-preview.100"
89+
context["node_kiota_bundle_version"] = "1.0.0-preview.102"
8990

9091
context["gha_checkout"] = "v6.0.2"
9192
context["gha_setup_python"] = "v6.2.0"
@@ -129,4 +130,5 @@ def hook( # noqa: PLR0915 # yes, this is a lot of statements, but it's all just
129130
# Kludge to be able to help symlinked jinja files in the child and grandchild templates
130131
context["template_uses_vuejs"] = False
131132
context["template_uses_typescript"] = False
133+
context["template_uses_python"] = True
132134
return context

‎pyproject.toml‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,12 @@ dependencies = [
1313
"pytest-cov>=7.1.0",
1414
"pytest-randomly>=4.1.0",
1515
"pyright[nodejs]>=1.1.409",
16-
"ty>=0.0.38",
16+
"ty>=0.0.40",
1717
"copier==9.15.1",
1818
"copier-template-extensions==0.3.3"
1919
]
20+
21+
[[tool.uv.index]]
22+
name = "pypi"
23+
url = "https://pypi.org/simple/"
24+
exclude-newer = "1 day"

0 commit comments

Comments
 (0)