7a0da7932b
OSV-Scanner (Scheduled) / scan-scheduled (push) Failing after 0s
Create Release / test-gate (push) Has been cancelled
Create Release / release-gate (push) Has been cancelled
Create Release / ci-gate (push) Has been cancelled
Create Release / version-check (push) Has been cancelled
Create Release / e2e-test-gate (push) Has been cancelled
Create Release / responsive-test-gate (push) Has been cancelled
Create Release / compat-test-gate (push) Has been cancelled
Create Release / compose-integration-gate (push) Has been cancelled
Create Release / vulture-gate (push) Has been cancelled
Create Release / build (push) Has been cancelled
Create Release / provenance (push) Has been cancelled
Create Release / prerelease-docker (push) Has been cancelled
Create Release / publish-docker (push) Has been cancelled
Create Release / create-release (push) Has been cancelled
Create Release / cleanup-changelog (push) Has been cancelled
Create Release / trigger-pypi (push) Has been cancelled
Create Release / monitor-pypi (push) Has been cancelled
Create Release / Clean up orphan prerelease tags and signatures (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-form] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-metrics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-workflow] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-core] (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [history-news] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [library] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [link-analytics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-core] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-lifecycle] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [error-benchmark] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) (push) Has been cancelled
Docker Tests (Consolidated) / Accessibility Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Unit Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Example Tests (push) Has been cancelled
Docker Tests (Consolidated) / Production Image Smoke Test (push) Has been cancelled
Docker Tests (Consolidated) / Infrastructure Tests (push) Has been cancelled
OSSF Scorecard / OSSF Security Scorecard Analysis (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [mobile] (push) Has been cancelled
Backwards Compatibility / Verify Encryption Constants (push) Has been cancelled
Backwards Compatibility / PyPI Version Compatibility (push) Has been cancelled
Backwards Compatibility / Database Migration Tests (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Docker Tests (Consolidated) / detect-changes (push) Has been cancelled
Docker Tests (Consolidated) / Build Test Image (push) Has been cancelled
Docker Tests (Consolidated) / All Pytest Tests + Coverage (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [accessibility] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [api-crud] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-login] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-register] (push) Has been cancelled
103 lines
5.9 KiB
Markdown
103 lines
5.9 KiB
Markdown
# ADR-0002: Pre-commit hook batch review
|
|
|
|
**Date:** 2026-03-28
|
|
**Status:** Accepted
|
|
|
|
## Context
|
|
|
|
Nine PRs proposing new or modified pre-commit hooks were evaluated
|
|
simultaneously. The repository already has 43 pre-commit hooks; new hooks must
|
|
clear a high bar for signal-to-noise ratio, speed, and non-duplication with CI.
|
|
|
|
Review was conducted using 86 automated review agents across 4 rounds,
|
|
cross-validating findings and verifying correctness of each recommendation.
|
|
|
|
## Decision
|
|
|
|
### Accepted (4 PRs)
|
|
|
|
| PR | Hook | Fix Applied |
|
|
|----|------|-------------|
|
|
| #3220 | fix(security): escape server data in innerHTML | None — merged as-is |
|
|
| #3221 | fix(config): sync ruff version (v0.14.10 → v0.15.8) | Full `ruff format .` pass to reformat all old-style lambdas |
|
|
| #3225 | chore(hooks): `raise ... from` enforcement in except blocks | None — merged as-is |
|
|
| #3219 | chore(hooks): layer-import boundary enforcement | Added `exclude: ^tests/` to prevent false positives on test files |
|
|
|
|
### Rejected (5 PRs)
|
|
|
|
**#3218 — utcnow callable check:** Directly contradicts the existing
|
|
`check-utcnow-parens` hook. `sqlalchemy_utc.utcnow` is a `FunctionElement`
|
|
class, so `utcnow()` creates a SQL expression rendered per-INSERT as
|
|
`CURRENT_TIMESTAMP`. The existing hook correctly requires parentheses. Having
|
|
both hooks would block every commit.
|
|
|
|
**#3222 — codespell (typo detection):** False-positives on camelCase identifiers
|
|
are a known, unsolved problem
|
|
([codespell-project/codespell#196](https://github.com/codespell-project/codespell/issues/196),
|
|
open since 2017). The tool treats `hasTable`, `doesnt`, `crasher`, and similar
|
|
code identifiers as misspellings, requiring an ever-growing ignore-words-list.
|
|
|
|
**#3227 — innerHTML regex scanner:** The core regex (`INTERPOLATION_RE` using
|
|
`[^}]+`) truncates at the first `}`, failing on nested braces in template
|
|
literals. Multiple real JS files are affected: `settings.js:80`,
|
|
`collection_details.js:210`, `history.js:421,501,503`,
|
|
`semantic_search.js:197-205`. This causes both false positives and false
|
|
negatives — unacceptable for a security tool. The project already has ESLint and
|
|
Bearer for JavaScript security analysis, both of which use proper AST-based
|
|
parsing. Use ESLint `no-unsanitized` rule instead.
|
|
|
|
**#3230 — vulture (dead code detection):** The hook used `language: system`,
|
|
which requires vulture on the system PATH and breaks in CI (the pre-commit
|
|
workflow does not install project dev dependencies). The larger issue is policy:
|
|
vulture is advisory-only in CI (release gate, not PR gate). Promoting it to a
|
|
blocking pre-commit hook is a policy escalation that should be a deliberate team
|
|
decision. Use the existing `vulture-dead-code.yml` CI workflow instead.
|
|
|
|
**#3231 — mypy (type checking):** Most production modules have
|
|
`ignore_errors = true` in `pyproject.toml` (`web.*`, `database.*`, `settings.*`,
|
|
`utilities.*`, `security.*`, `api.*`, and 8+ more). mypy already blocks PRs via
|
|
`mypy-type-check.yml` + `ci-gate.yml`. Adding it as a pre-commit hook would add
|
|
10-30 seconds per commit for near-zero detection value on the majority of the
|
|
codebase.
|
|
|
|
## Consequences
|
|
|
|
- Four new hooks strengthen the pre-commit pipeline (XSS prevention, ruff
|
|
consistency, exception chaining, architectural boundaries)
|
|
- Five proposals are documented as rejected with specific technical reasons,
|
|
preventing re-proposals without new information
|
|
- Rejected hooks are listed in `.pre-commit-config.yaml` comments with a link
|
|
to this document
|
|
- The total hook count increases from 43 to 45, with negligible performance
|
|
impact (~100-200ms per commit for the new hooks)
|
|
|
|
## Principles for future hook proposals
|
|
|
|
1. **Fast**: target under 3 seconds for a typical staged-file set.
|
|
2. **Scoped appropriately**: file-scoped hooks are preferred. Hooks requiring
|
|
full-repo analysis need a narrow `files:` trigger and team consensus.
|
|
3. **High local value**: don't add slow CI checks to pre-commit when the local
|
|
feedback value is low (e.g., mypy with most modules ignored).
|
|
4. **Validated**: run the hook against the existing codebase before proposing.
|
|
5. **Low false-positive rate**: if suppressions are needed from day one,
|
|
reconsider whether the hook belongs here.
|
|
6. **Low false-positive on identifiers**: tools designed for natural language
|
|
may over-fire on camelCase identifiers, abbreviations, and domain terms.
|
|
7. **Self-contained**: hooks must work in pre-commit's CI workflow without
|
|
requiring system-level dependencies (`language: python` with
|
|
`additional_dependencies`, not `language: system`).
|
|
|
|
## Related PRs
|
|
|
|
| PR | Title | Decision |
|
|
|----|-------|----------|
|
|
| [#3218](https://github.com/LearningCircuit/local-deep-research/pull/3218) | chore(hooks): prevent frozen utcnow() | Rejected — conflicts with existing hook |
|
|
| [#3219](https://github.com/LearningCircuit/local-deep-research/pull/3219) | chore(hooks): layer-import boundary enforcement | Accepted (fix: `exclude: ^tests/`) |
|
|
| [#3220](https://github.com/LearningCircuit/local-deep-research/pull/3220) | fix(security): escape server data in innerHTML | Accepted |
|
|
| [#3221](https://github.com/LearningCircuit/local-deep-research/pull/3221) | fix(config): sync ruff version | Accepted (fix: full `ruff format .`) |
|
|
| [#3222](https://github.com/LearningCircuit/local-deep-research/pull/3222) | chore(hooks): add codespell typo detection | Rejected — CamelCase false positives |
|
|
| [#3225](https://github.com/LearningCircuit/local-deep-research/pull/3225) | chore(hooks): `raise ... from` in except blocks | Accepted |
|
|
| [#3227](https://github.com/LearningCircuit/local-deep-research/pull/3227) | chore(hooks): detect unescaped innerHTML | Rejected — regex bug |
|
|
| [#3230](https://github.com/LearningCircuit/local-deep-research/pull/3230) | chore(hooks): vulture dead code detection | Rejected — policy escalation |
|
|
| [#3231](https://github.com/LearningCircuit/local-deep-research/pull/3231) | chore(hooks): mypy type checking | Rejected — already in CI |
|