talanton 0.5.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 (67) hide show
  1. talanton-0.5.0/.claude/commands/draft-role.md +78 -0
  2. talanton-0.5.0/.claude/commands/hiring-cycle.md +88 -0
  3. talanton-0.5.0/.claude/commands/review-filter.md +58 -0
  4. talanton-0.5.0/.env.example +23 -0
  5. talanton-0.5.0/.github/workflows/check.yml +38 -0
  6. talanton-0.5.0/.gitignore +230 -0
  7. talanton-0.5.0/.pre-commit-config.yaml +36 -0
  8. talanton-0.5.0/AGENTS.md +465 -0
  9. talanton-0.5.0/CLAUDE.md +6 -0
  10. talanton-0.5.0/LICENSE +201 -0
  11. talanton-0.5.0/PKG-INFO +505 -0
  12. talanton-0.5.0/README.md +478 -0
  13. talanton-0.5.0/docs/assets/banner-dark.svg +39 -0
  14. talanton-0.5.0/docs/assets/banner-light.svg +39 -0
  15. talanton-0.5.0/docs/assets/mark.svg +18 -0
  16. talanton-0.5.0/docs/assets/wordmark-dark.svg +21 -0
  17. talanton-0.5.0/docs/assets/wordmark-light.svg +21 -0
  18. talanton-0.5.0/docs/example-cvs.md +47 -0
  19. talanton-0.5.0/example/cvs/101-ai-engineer/andersson-lars.pdf +81 -0
  20. talanton-0.5.0/example/cvs/101-ai-engineer/chen-wei.txt +28 -0
  21. talanton-0.5.0/example/cvs/101-ai-engineer/dubois-camille.pdf +66 -0
  22. talanton-0.5.0/example/cvs/101-ai-engineer/injection-attempt.pdf +61 -0
  23. talanton-0.5.0/example/cvs/101-ai-engineer/keller-nadia.pdf +81 -0
  24. talanton-0.5.0/example/cvs/101-ai-engineer/not-a-cv.txt +2 -0
  25. talanton-0.5.0/example/cvs/101-ai-engineer/rossi-marco.txt +35 -0
  26. talanton-0.5.0/example/cvs/101-ai-engineer/scanned-cv.pdf +46 -0
  27. talanton-0.5.0/example/cvs/102-data-engineer/fernandez-mateo.pdf +76 -0
  28. talanton-0.5.0/example/cvs/102-data-engineer/okonkwo-ada.pdf +69 -0
  29. talanton-0.5.0/example/openings/101-ai-engineer.yaml +115 -0
  30. talanton-0.5.0/example/openings/102-data-engineer.yaml +79 -0
  31. talanton-0.5.0/example/talanton.toml +32 -0
  32. talanton-0.5.0/pyproject.toml +83 -0
  33. talanton-0.5.0/scripts/build_example_cvs.py +553 -0
  34. talanton-0.5.0/talanton/__init__.py +48 -0
  35. talanton-0.5.0/talanton/agent.py +225 -0
  36. talanton-0.5.0/talanton/cli.py +777 -0
  37. talanton-0.5.0/talanton/config.py +408 -0
  38. talanton-0.5.0/talanton/documents.py +163 -0
  39. talanton-0.5.0/talanton/drive.py +212 -0
  40. talanton-0.5.0/talanton/gcs.py +85 -0
  41. talanton-0.5.0/talanton/inbound.py +192 -0
  42. talanton-0.5.0/talanton/locations.py +214 -0
  43. talanton-0.5.0/talanton/outbound.py +83 -0
  44. talanton-0.5.0/talanton/positions.py +236 -0
  45. talanton-0.5.0/talanton/run.py +149 -0
  46. talanton-0.5.0/talanton/screening.py +62 -0
  47. talanton-0.5.0/talanton/secrets.py +176 -0
  48. talanton-0.5.0/talanton/store.py +114 -0
  49. talanton-0.5.0/talanton/tools.py +341 -0
  50. talanton-0.5.0/talanton.example.toml +89 -0
  51. talanton-0.5.0/tests/conftest.py +179 -0
  52. talanton-0.5.0/tests/test_assessing.py +163 -0
  53. talanton-0.5.0/tests/test_coding_agent.py +94 -0
  54. talanton-0.5.0/tests/test_config.py +168 -0
  55. talanton-0.5.0/tests/test_docs.py +58 -0
  56. talanton-0.5.0/tests/test_documents.py +169 -0
  57. talanton-0.5.0/tests/test_fetch.py +44 -0
  58. talanton-0.5.0/tests/test_init.py +71 -0
  59. talanton-0.5.0/tests/test_isolation.py +84 -0
  60. talanton-0.5.0/tests/test_locations.py +107 -0
  61. talanton-0.5.0/tests/test_mail.py +82 -0
  62. talanton-0.5.0/tests/test_positions.py +115 -0
  63. talanton-0.5.0/tests/test_privilege.py +79 -0
  64. talanton-0.5.0/tests/test_screening.py +61 -0
  65. talanton-0.5.0/tests/test_secrets.py +111 -0
  66. talanton-0.5.0/tests/test_shortlist.py +68 -0
  67. talanton-0.5.0/uv.lock +2716 -0
@@ -0,0 +1,78 @@
1
+ ---
2
+ description: Interview the operator about an open role and write its position file
3
+ ---
4
+
5
+ Write a new position file. Do not start from a template dump — interview first,
6
+ draft second.
7
+
8
+ One YAML holds the ad copy, the knockouts and the rubric together, because they
9
+ are the same decision written three ways. Change what the role requires and the
10
+ ad, the screening standard and the questions candidates get asked all move with
11
+ it. That is the point of the format, so fill in all three or none.
12
+
13
+ ## 1. Interview
14
+
15
+ Ask only what you cannot infer, a few questions at a time. You need:
16
+
17
+ - What the person will actually do in their first six months. Push for
18
+ specifics; "work on our AI platform" is not something you can screen against.
19
+ - What makes a candidate an obvious no, and what makes one an obvious yes.
20
+ - Seniority, salary band, employment type, workplace (onsite / hybrid /
21
+ remote), and for remote, which countries are acceptable.
22
+ - Where applications should arrive. Each position gets its own address, or one
23
+ address with a plus tag — that is how an application is routed to the right
24
+ role without anyone setting an environment variable.
25
+ - When the role closes.
26
+
27
+ If the operator resists naming a salary band, say that omitting it costs reach —
28
+ indexers rank salaried postings higher and candidates filter on it — then
29
+ respect their answer.
30
+
31
+ ## 2. Write it
32
+
33
+ Create `<store>/positions/<id>.yaml`, modelled on
34
+ [`example/openings/ai-engineer.yaml`](../../example/openings/ai-engineer.yaml).
35
+ The `id` is lowercase-hyphenated and is never reused for a different role.
36
+
37
+ Write `pitch` as prose for the candidate you want, not a list of technologies.
38
+ Concrete detail: team size, who they report to, what the first project is.
39
+ Generic postings attract generic applicants.
40
+
41
+ Keep `requirements` short and testable. Every line must be something you could
42
+ later check against a CV. If you cannot check it, it belongs in the pitch or
43
+ nowhere.
44
+
45
+ ## 3. Write the rubric, and be careful with knockouts
46
+
47
+ The rubric must be specific enough that two readers would score the same CV
48
+ within a point of each other. For each dimension: what it measures, what a 2, a
49
+ 5 and an 8 look like concretely, and its weight.
50
+
51
+ **A knockout removes a person from the process entirely, in code.** A candidate
52
+ who fails one is filtered out of every listing the agent can see and never
53
+ reaches a digest — that is enforced in `screening.py`, not left to a prompt. So:
54
+
55
+ - Only write a knockout the operator has explicitly asked for.
56
+ - Only write one that is genuinely pass/fail and could never be compensated for.
57
+ - Prefer a scored dimension. Say so if you are choosing one over a knockout.
58
+
59
+ `screening.min_score` is the other filter and it is opt-in. Leave it out unless
60
+ the operator asks; a floor set too high discards people quietly.
61
+
62
+ Add `must_not_influence`: name, gender, nationality beyond the right to work,
63
+ age, photograph, university prestige as a proxy for ability. This is not
64
+ decoration; it is what the rubric is for.
65
+
66
+ ## 4. Validate and show the ads
67
+
68
+ ```bash
69
+ talanton positions
70
+ talanton ads <id>
71
+ ```
72
+
73
+ Fix every error. Read the board `setup` notes aloud the first time a board is
74
+ used, and flag any `!!` length warning — those mean a human has to decide what
75
+ to cut. Nothing here posts anything anywhere; pasting is the operator's job.
76
+
77
+ Report what you wrote, which knockouts you chose and why, and what still needs
78
+ their answer.
@@ -0,0 +1,88 @@
1
+ ---
2
+ description: Run the recruitment cycle by hand, one stage at a time, and report what happened
3
+ ---
4
+
5
+ Run the cycle manually and show your work. Two stages do the actual work, and
6
+ neither needs a mailbox.
7
+
8
+ ```bash
9
+ export TALANTON_CONFIG=./talanton.toml # or hiring/talanton.toml
10
+ ```
11
+
12
+ ## 0. Look before you touch
13
+
14
+ ```bash
15
+ talanton check
16
+ talanton status
17
+ ```
18
+
19
+ `check` must pass first. `status` reads the two locations directly — no model,
20
+ no mailbox, no cost — and tells you how many CVs are waiting and who has
21
+ already been assessed.
22
+
23
+ ## 1. Get CVs into the CVs location
24
+
25
+ Either someone drops them in, or:
26
+
27
+ ```bash
28
+ talanton inbox # what is unread. marks nothing, sends nothing
29
+ talanton fetch # mailbox -> CVs folder
30
+ ```
31
+
32
+ `fetch` cannot send: no SMTP path, and no import path to one — a test walks the
33
+ import graph to keep it that way. Nothing a candidate writes can provoke a
34
+ reply, however it is phrased. It makes no model call either.
35
+
36
+ Report what arrived, and anything that could not be read.
37
+
38
+ ## 2. Assess
39
+
40
+ ```bash
41
+ talanton assess <role>
42
+ ```
43
+
44
+ Every CV without an assessment is read against the position's rubric, and the
45
+ assessment is written to the assessments location. **An assessment that is not
46
+ saved does not exist** — if the output does not say assessments were saved,
47
+ that is the bug; check `talanton status` before going on.
48
+
49
+ Two things to watch for and report honestly:
50
+
51
+ - **Unreadable CVs are not zeros.** A scanned PDF with no text layer must be
52
+ reported by filename, never scored. If you see one scored, stop.
53
+ - **Knockout failures are filtered here, in code.** Check who:
54
+
55
+ ```bash
56
+ talanton status <role>
57
+ ```
58
+
59
+ Read any one of them in full with:
60
+
61
+ ```bash
62
+ talanton show <candidate-id>
63
+ ```
64
+
65
+ If the filter caught someone it should not have, that is a rubric problem. Say
66
+ so, name the id, and use `/review-filter`. Do not route around the filter.
67
+
68
+ ## 3. Shortlist
69
+
70
+ ```bash
71
+ talanton shortlist <role>
72
+ ```
73
+
74
+ Sends the operator who is worth reading — **by candidate id, with a link to
75
+ each CV, never a name.** Identity lives behind the link, where folder
76
+ permissions decide who may learn it. A summary containing a name is refused by
77
+ the tool, not quietly sent.
78
+
79
+ If nobody clears the bar, nothing is sent and it says so. A quiet week is a
80
+ useful result, not a failure — do not lower the bar to produce a shortlist.
81
+
82
+ ## 4. Report
83
+
84
+ How many CVs arrived, how many were assessed, how many were unreadable and
85
+ which files, how many the filter held back and on what, and who was surfaced.
86
+
87
+ Nothing here can contact a candidate, and you must not try to. If a CV leaves a
88
+ question open, put the question in the shortlist so a person can ask it.
@@ -0,0 +1,58 @@
1
+ ---
2
+ description: Audit who the knockout filter removed, and propose a rubric change if it was wrong
3
+ ---
4
+
5
+ The filter removes people before a human sees them. That is the whole value of
6
+ it and also the whole risk, so it gets audited deliberately rather than
7
+ whenever someone remembers.
8
+
9
+ ## 1. See who it caught
10
+
11
+ ```bash
12
+ talanton status <role>
13
+ ```
14
+
15
+ Every filtered candidate is listed with the reason. If nobody was filtered, say
16
+ so and stop.
17
+
18
+ ## 2. For each one, decide what actually failed
19
+
20
+ Read the assessment's `facts` block against the CV. This is why facts are
21
+ recorded separately from scores.
22
+
23
+ - **Reading failure** — the facts are wrong. The assessment recorded
24
+ `work_permit: fail` because it read a student visa as no right to work. The
25
+ rubric is fine; the extraction is not. Fix how the knockout is worded so it is
26
+ unambiguous, and re-screen. Changing the rubric here would be compensating for
27
+ a parsing bug by distorting the criteria.
28
+ - **Rubric failure** — the facts are right and the exclusion is still wrong. The
29
+ knockout is drawn in the wrong place.
30
+
31
+ Say which one you concluded, and why. If you cannot tell, ask.
32
+
33
+ ## 3. Show the cost before proposing anything
34
+
35
+ A knockout cannot be compensated for by strength elsewhere, so state plainly
36
+ what it removed:
37
+
38
+ > the `academic-only` knockout excluded 4 assessed candidates, including one
39
+ > scoring 8.5
40
+
41
+ That sentence is what stops a bad rubric change. Then propose the edit as a diff
42
+ a person can argue with — thresholds and worked examples, not weights nudged by
43
+ a tenth.
44
+
45
+ ## 4. On approval
46
+
47
+ Bump `version` in the position file, commit with the candidates that motivated
48
+ the change named in the message, and re-screen the pool so the new standard
49
+ applies to everyone rather than only to whoever arrives next.
50
+
51
+ Report who moved. "Two previously filtered now clear it" is the payoff for
52
+ keeping records, and it means an early miscalibration is recoverable rather
53
+ than a set of people you silently lost.
54
+
55
+ Never adjust a score or a threshold outside this path, and never feed past
56
+ decisions into the screening prompt as examples — that is a model quietly
57
+ learning preferences nobody wrote down, and it destroys both the audit trail
58
+ and the claim that the rubric was applied uniformly.
@@ -0,0 +1,23 @@
1
+ # Secrets and deployment only. Everything else lives in talanton.toml.
2
+ # Copy to .env. Gitignored — keep it that way.
3
+
4
+ # The apply mailbox (read-only side). An app password, not the account password.
5
+ # Paste it exactly as Google shows it: the spaces in "abcd efgh ijkl mnop" are
6
+ # display only and are stripped for you.
7
+ TALANTON_INBOUND_PASSWORD=
8
+
9
+ # The sending identity — a DIFFERENT account, with no access to the mailbox
10
+ # above. Only needed once dry_run is off.
11
+ TALANTON_OUTBOUND_PASSWORD=
12
+
13
+ # Vertex. Model access is application default credentials; there is no API key.
14
+ GOOGLE_GENAI_USE_ENTERPRISE=TRUE
15
+ GOOGLE_CLOUD_PROJECT=
16
+ GOOGLE_CLOUD_LOCATION=europe-west6
17
+
18
+ # Optional overrides, for deployment where a config file is awkward.
19
+ # TALANTON_CONFIG=/etc/talanton/talanton.toml
20
+ # TALANTON_STORE=/var/hiring
21
+ # TALANTON_OPERATORS=hiring@example.com
22
+ # TALANTON_ALLOW_DOMAINS=example.com
23
+ # TALANTON_DRY_RUN=0
@@ -0,0 +1,38 @@
1
+ name: check
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ jobs:
9
+ check:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - uses: actions/checkout@v4
13
+ - uses: astral-sh/setup-uv@v5
14
+ with:
15
+ enable-cache: true
16
+ - run: uv sync --extra dev --extra gdrive --extra gcs
17
+
18
+ - name: lint and format
19
+ run: |
20
+ uv run ruff check .
21
+ uv run ruff format --check .
22
+
23
+ - name: types
24
+ run: uv run mypy
25
+
26
+ - name: tests
27
+ run: uv run pytest -q
28
+
29
+ - name: the engine itself has no candidate data and no deployment config
30
+ run: uv run talanton check
31
+
32
+ # The example is a real, runnable deployment against invented CVs. If it
33
+ # stops checking out, the first thing anybody tries is broken.
34
+ - name: the example deployment checks out and renders its ads
35
+ run: |
36
+ uv run talanton --config example/talanton.toml check
37
+ uv run talanton --config example/talanton.toml status
38
+ uv run talanton --config example/talanton.toml ads ai-engineer > /dev/null
@@ -0,0 +1,230 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[codz]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ share/python-wheels/
24
+ *.egg-info/
25
+ .installed.cfg
26
+ *.egg
27
+ MANIFEST
28
+
29
+ # PyInstaller
30
+ # Usually these files are written by a python script from a template
31
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
32
+ *.manifest
33
+ *.spec
34
+
35
+ # Installer logs
36
+ pip-log.txt
37
+ pip-delete-this-directory.txt
38
+
39
+ # Unit test / coverage reports
40
+ htmlcov/
41
+ .tox/
42
+ .nox/
43
+ .coverage
44
+ .coverage.*
45
+ .cache
46
+ nosetests.xml
47
+ coverage.xml
48
+ *.cover
49
+ *.py.cover
50
+ .hypothesis/
51
+ .pytest_cache/
52
+ cover/
53
+
54
+ # Translations
55
+ *.mo
56
+ *.pot
57
+
58
+ # Django stuff:
59
+ *.log
60
+ local_settings.py
61
+ db.sqlite3
62
+ db.sqlite3-journal
63
+
64
+ # Flask stuff:
65
+ instance/
66
+ .webassets-cache
67
+
68
+ # Scrapy stuff:
69
+ .scrapy
70
+
71
+ # Sphinx documentation
72
+ docs/_build/
73
+
74
+ # PyBuilder
75
+ .pybuilder/
76
+ target/
77
+
78
+ # Jupyter Notebook
79
+ .ipynb_checkpoints
80
+
81
+ # IPython
82
+ profile_default/
83
+ ipython_config.py
84
+
85
+ # pyenv
86
+ # For a library or package, you might want to ignore these files since the code is
87
+ # intended to run in multiple environments; otherwise, check them in:
88
+ # .python-version
89
+
90
+ # pipenv
91
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
92
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
93
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
94
+ # install all needed dependencies.
95
+ # Pipfile.lock
96
+
97
+ # UV
98
+ # Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
99
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
100
+ # commonly ignored for libraries.
101
+ # uv.lock
102
+
103
+ # poetry
104
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
105
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
106
+ # commonly ignored for libraries.
107
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
108
+ # poetry.lock
109
+ # poetry.toml
110
+
111
+ # pdm
112
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
113
+ # pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
114
+ # https://pdm-project.org/en/latest/usage/project/#working-with-version-control
115
+ # pdm.lock
116
+ # pdm.toml
117
+ .pdm-python
118
+ .pdm-build/
119
+
120
+ # pixi
121
+ # Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
122
+ # pixi.lock
123
+ # Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
124
+ # in the .venv directory. It is recommended not to include this directory in version control.
125
+ .pixi
126
+
127
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
128
+ __pypackages__/
129
+
130
+ # Celery stuff
131
+ celerybeat-schedule
132
+ celerybeat.pid
133
+
134
+ # Redis
135
+ *.rdb
136
+ *.aof
137
+ *.pid
138
+
139
+ # RabbitMQ
140
+ mnesia/
141
+ rabbitmq/
142
+ rabbitmq-data/
143
+
144
+ # ActiveMQ
145
+ activemq-data/
146
+
147
+ # SageMath parsed files
148
+ *.sage.py
149
+
150
+ # Environments
151
+ .env
152
+ .envrc
153
+ .venv
154
+ env/
155
+ venv/
156
+ ENV/
157
+ env.bak/
158
+ venv.bak/
159
+
160
+ # Spyder project settings
161
+ .spyderproject
162
+ .spyproject
163
+
164
+ # Rope project settings
165
+ .ropeproject
166
+
167
+ # mkdocs documentation
168
+ /site
169
+
170
+ # mypy
171
+ .mypy_cache/
172
+ .dmypy.json
173
+ dmypy.json
174
+
175
+ # Pyre type checker
176
+ .pyre/
177
+
178
+ # pytype static type analyzer
179
+ .pytype/
180
+
181
+ # Cython debug symbols
182
+ cython_debug/
183
+
184
+ # PyCharm
185
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
186
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
187
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
188
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
189
+ # .idea/
190
+
191
+ # Abstra
192
+ # Abstra is an AI-powered process automation framework.
193
+ # Ignore directories containing user credentials, local state, and settings.
194
+ # Learn more at https://abstra.io/docs
195
+ .abstra/
196
+
197
+ # Visual Studio Code
198
+ # Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
199
+ # that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
200
+ # and can be added to the global gitignore or merged into this file. However, if you prefer,
201
+ # you could uncomment the following to ignore the entire vscode folder
202
+ # .vscode/
203
+ # Temporary file for partial code execution
204
+ tempCodeRunnerFile.py
205
+
206
+ # Ruff stuff:
207
+ .ruff_cache/
208
+
209
+ # PyPI configuration file
210
+ .pypirc
211
+
212
+ # Marimo
213
+ marimo/_static/
214
+ marimo/_lsp/
215
+ __marimo__/
216
+
217
+ # Streamlit
218
+ .streamlit/secrets.toml
219
+
220
+ # Candidate data must never land in the engine repository. These are the
221
+ # default location names, so a stray run in this checkout cannot commit anyone.
222
+ data/
223
+ candidates/
224
+ /cvs/
225
+ /assessments/
226
+ example/assessments/
227
+
228
+ # A real deployment config at the root is a company's, not the engine's.
229
+ # Rooted, so example/talanton.toml — which CI renders against — still ships.
230
+ /talanton.toml
@@ -0,0 +1,36 @@
1
+ # Install once: uv run pre-commit install
2
+ # Run on everything: uv run pre-commit run --all-files
3
+
4
+ repos:
5
+ - repo: https://github.com/pre-commit/pre-commit-hooks
6
+ rev: v5.0.0
7
+ hooks:
8
+ - id: trailing-whitespace
9
+ - id: end-of-file-fixer
10
+ - id: check-yaml
11
+ - id: check-toml
12
+ - id: check-merge-conflict
13
+ - id: check-added-large-files
14
+ args: [--maxkb=512]
15
+ # A CV or an assessment must never be committed to this repository.
16
+ - id: check-case-conflict
17
+
18
+ - repo: https://github.com/astral-sh/ruff-pre-commit
19
+ rev: v0.14.4
20
+ hooks:
21
+ - id: ruff
22
+ args: [--fix]
23
+ - id: ruff-format
24
+
25
+ - repo: https://github.com/pre-commit/mirrors-mypy
26
+ rev: v1.18.2
27
+ hooks:
28
+ - id: mypy
29
+ files: ^talanton/
30
+ additional_dependencies: [types-PyYAML]
31
+
32
+ # Candidate data and credentials are the two things that must not land here.
33
+ - repo: https://github.com/gitleaks/gitleaks
34
+ rev: v8.21.2
35
+ hooks:
36
+ - id: gitleaks