-
Notifications
You must be signed in to change notification settings - Fork 14
Feat: PR diff viewer, finding verification pass, and account settings with timezone-aware stats #55
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
7e41598
993af70
9ebc5cd
f93be3f
6eb0808
3c3380d
75136c7
3115e19
59a5ce2
09330f9
ef81807
b164e0c
a7bd5aa
aa79fd1
7485d21
e251766
eec7d57
260738c
e29cfd2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -4,8 +4,12 @@ updates: | |||||
| directory: "/" | ||||||
| schedule: | ||||||
| interval: "weekly" | ||||||
| cooldown: | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The 'cooldown' key is not a valid configuration option for the 'updates' block in Dependabot. This will cause the Dependabot configuration to fail validation, preventing automated dependency updates.
Suggested change
|
||||||
| default-days: 7 | ||||||
|
|
||||||
| - package-ecosystem: "github-actions" | ||||||
| directory: "/" | ||||||
| schedule: | ||||||
| interval: "weekly" | ||||||
| cooldown: | ||||||
| default-days: 7 | ||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -49,10 +49,10 @@ jobs: | |||||||||||||
|
|
||||||||||||||
| steps: | ||||||||||||||
| - name: Checkout repository | ||||||||||||||
| uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 | ||||||||||||||
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | ||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The diff updates
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The diff updates
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The diff attempts to use version 'v7.0.0' for 'actions/checkout' and 'actions/setup-node'. As of current GitHub Actions releases, both 'actions/checkout' and 'actions/setup-node' are on major version 4. There is no v7.0.0 for these official actions, which will cause the CI workflow to fail because the specified action version does not exist.
Suggested change
|
||||||||||||||
|
|
||||||||||||||
| - name: Setup Node.js | ||||||||||||||
| uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 | ||||||||||||||
| uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 | ||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The specified version 'v7.0.0' for 'actions/setup-node' does not exist. The latest major version is v4. Using a non-existent tag will cause the CI workflow to fail.
Suggested change
|
||||||||||||||
| with: | ||||||||||||||
| node-version: 20 | ||||||||||||||
| cache: 'npm' | ||||||||||||||
|
|
||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -22,12 +22,12 @@ jobs: | |||||||||||||
|
|
||||||||||||||
| steps: | ||||||||||||||
| - name: Checkout repository | ||||||||||||||
| uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 | ||||||||||||||
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | ||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The diff specifies 'actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0' labeled as 'v7.0.0'. As of current releases, the latest major version for actions/checkout is v4. Version v7.0.0 does not exist and may cause the workflow to fail if it points to an invalid tag, branch, or commit that does not align with the action's intended repository state.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The diff attempts to upgrade
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The diff specifies 'actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0'. As of current GitHub Actions releases, 'actions/checkout' version 'v7.0.0' does not exist. The latest major version is v4. Specifying a non-existent tag will cause the workflow to fail to resolve the action.
Suggested change
|
||||||||||||||
|
|
||||||||||||||
| - name: Initialize CodeQL | ||||||||||||||
| uses: github/codeql-action/init@411c4c9a36b3fca4d674f06b6396b2c6d23522c6 # v3.36.3 | ||||||||||||||
| uses: github/codeql-action/init@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0 | ||||||||||||||
| with: | ||||||||||||||
| languages: ${{ matrix.language }} | ||||||||||||||
|
|
||||||||||||||
| - name: Perform CodeQL Analysis | ||||||||||||||
| uses: github/codeql-action/analyze@411c4c9a36b3fca4d674f06b6396b2c6d23522c6 # v3.36.3 | ||||||||||||||
| uses: github/codeql-action/analyze@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0 | ||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -143,3 +143,4 @@ vite.config.ts.timestamp-* | |
| .wrangler | ||
|
|
||
| .agent | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,102 @@ | ||
| CREATE TABLE IF NOT EXISTS account_settings ( | ||
| id UUID PRIMARY KEY DEFAULT gen_random_uuid(), | ||
| github_user_id BIGINT NOT NULL UNIQUE, | ||
| github_username TEXT NOT NULL, | ||
| account_name TEXT, | ||
| account_email TEXT, | ||
|
|
||
| timezone TEXT, | ||
| created_at TIMESTAMPTZ NOT NULL DEFAULT now(), | ||
| updated_at TIMESTAMPTZ NOT NULL DEFAULT now() | ||
| ); | ||
|
|
||
| ALTER TABLE account_settings ADD COLUMN IF NOT EXISTS timezone TEXT; | ||
|
|
||
| ALTER TABLE review_comments ADD COLUMN IF NOT EXISTS confidence_score REAL; | ||
|
|
||
| ALTER TABLE review_comments ADD COLUMN IF NOT EXISTS evidence TEXT COMPRESSION lz4; | ||
| ALTER TABLE review_comments ADD COLUMN IF NOT EXISTS fingerprint TEXT; | ||
| ALTER TABLE review_comments ADD COLUMN IF NOT EXISTS anchor_hash TEXT; | ||
| ALTER TABLE review_comments ADD COLUMN IF NOT EXISTS posted BOOLEAN NOT NULL DEFAULT FALSE; | ||
|
|
||
| CREATE INDEX IF NOT EXISTS review_comments_posted_fingerprint_idx | ||
| ON review_comments (file_review_id, fingerprint) | ||
| WHERE posted AND fingerprint IS NOT NULL; | ||
|
|
||
| CREATE TABLE IF NOT EXISTS comment_feedback ( | ||
| id BIGSERIAL PRIMARY KEY, | ||
| repository_id INTEGER NOT NULL REFERENCES repositories(id) ON DELETE CASCADE, | ||
| pr_number INTEGER, | ||
| fingerprint TEXT NOT NULL, | ||
| anchor_hash TEXT, | ||
| github_comment_id BIGINT NOT NULL, | ||
| outcome TEXT NOT NULL, | ||
| created_at TIMESTAMPTZ NOT NULL DEFAULT now() | ||
| ); | ||
|
|
||
| CREATE UNIQUE INDEX IF NOT EXISTS comment_feedback_unique_idx | ||
| ON comment_feedback (repository_id, github_comment_id, outcome); | ||
|
|
||
| CREATE INDEX IF NOT EXISTS comment_feedback_repo_outcome_idx | ||
| ON comment_feedback (repository_id, outcome); | ||
|
|
||
| DO $backfill$ | ||
| BEGIN | ||
| IF EXISTS ( | ||
| SELECT 1 FROM schema_migrations | ||
| WHERE name IN ( | ||
| '003_clear_stored_diff_input.sql', | ||
| '003_diff_accounts.sql', | ||
| '004_account_timezone.sql', | ||
| '004_xai_provider.sql', | ||
| '005_review_comments_confidence_score.sql', | ||
| '006_review_comment_grounding.sql', | ||
| '007_comment_feedback.sql', | ||
| '008_repo_config_min_severity.sql' | ||
| ) | ||
| ) THEN | ||
| RAISE NOTICE 'Pre-consolidation migrations already applied; skipping data backfills.'; | ||
| RETURN; | ||
| END IF; | ||
|
|
||
| UPDATE file_reviews SET diff_input = NULL WHERE diff_input IS NOT NULL; | ||
|
|
||
| INSERT INTO llm_providers (name, api_format, base_url, enabled) | ||
| VALUES ('xAI', 'openai', 'https://api.x.ai/v1', FALSE) | ||
| ON CONFLICT (name) DO UPDATE SET | ||
| api_format = EXCLUDED.api_format, | ||
| base_url = EXCLUDED.base_url, | ||
| updated_at = now(); | ||
| END | ||
| $backfill$; | ||
|
|
||
| UPDATE repo_configs | ||
| SET parsed_json = to_jsonb( | ||
| jsonb_set((parsed_json #>> '{}')::jsonb, '{review,min_severity}', '"P3"')::text | ||
| ), | ||
| updated_at = now() | ||
| WHERE jsonb_typeof(parsed_json) = 'string' | ||
| AND (parsed_json #>> '{}')::jsonb->'review'->>'min_severity' = 'nit'; | ||
|
|
||
| UPDATE repo_configs | ||
| SET parsed_json = jsonb_set(parsed_json, '{review,min_severity}', '"P3"'), | ||
| updated_at = now() | ||
| WHERE jsonb_typeof(parsed_json) = 'object' | ||
| AND parsed_json->'review'->>'min_severity' = 'nit'; | ||
|
|
||
| INSERT INTO global_settings (key, value) VALUES ('review_max_files', '200') | ||
| ON CONFLICT (key) DO NOTHING; | ||
|
|
||
| UPDATE repo_configs | ||
| SET parsed_json = to_jsonb( | ||
| ((parsed_json #>> '{}')::jsonb #- '{review,max_files}')::text | ||
| ), | ||
| updated_at = now() | ||
| WHERE jsonb_typeof(parsed_json) = 'string' | ||
| AND (parsed_json #>> '{}')::jsonb->'review' ? 'max_files'; | ||
|
|
||
| UPDATE repo_configs | ||
| SET parsed_json = parsed_json #- '{review,max_files}', | ||
| updated_at = now() | ||
| WHERE jsonb_typeof(parsed_json) = 'object' | ||
| AND parsed_json->'review' ? 'max_files'; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| ALTER TABLE review_comments ADD COLUMN IF NOT EXISTS claim_type TEXT; | ||
| ALTER TABLE review_comments ADD COLUMN IF NOT EXISTS context_snippet TEXT COMPRESSION lz4; | ||
| ALTER TABLE review_comments ADD COLUMN IF NOT EXISTS disposition TEXT; | ||
|
|
||
| CREATE INDEX IF NOT EXISTS review_comments_claim_type_idx | ||
| ON review_comments (claim_type) | ||
| WHERE claim_type IS NOT NULL; |
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,28 @@ | ||||||||||
| ALTER TABLE review_comments ADD COLUMN IF NOT EXISTS verify_reason TEXT COMPRESSION lz4; | ||||||||||
| ALTER TABLE file_reviews ADD COLUMN IF NOT EXISTS withheld_counts JSONB; | ||||||||||
|
|
||||||||||
| ALTER TABLE comment_feedback ADD COLUMN IF NOT EXISTS source TEXT NOT NULL DEFAULT 'github_webhook'; | ||||||||||
| ALTER TABLE comment_feedback ALTER COLUMN github_comment_id DROP NOT NULL; | ||||||||||
| ALTER TABLE comment_feedback ADD COLUMN IF NOT EXISTS job_id UUID REFERENCES jobs(id) ON DELETE SET NULL; | ||||||||||
| ALTER TABLE comment_feedback ADD COLUMN IF NOT EXISTS labelled_by BIGINT; | ||||||||||
| ALTER TABLE comment_feedback ADD COLUMN IF NOT EXISTS updated_at TIMESTAMPTZ NOT NULL DEFAULT now(); | ||||||||||
|
|
||||||||||
| CREATE UNIQUE INDEX IF NOT EXISTS comment_feedback_dashboard_unique_idx | ||||||||||
| ON comment_feedback (repository_id, fingerprint) | ||||||||||
| WHERE source = 'dashboard'; | ||||||||||
|
|
||||||||||
| CREATE INDEX IF NOT EXISTS comment_feedback_repo_fingerprint_idx | ||||||||||
| ON comment_feedback (repository_id, fingerprint); | ||||||||||
|
|
||||||||||
| UPDATE repo_configs | ||||||||||
| SET parsed_json = to_jsonb( | ||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The migration performs a complex cast of JSONB to text and back to JSONB inside an UPDATE statement. Specifically,
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The migration attempts to update a JSONB column by casting it to text, performing a jsonb_set, and then casting it back to jsonb. However, the use of
Suggested change
|
||||||||||
| jsonb_set( | ||||||||||
| (parsed_json #>> '{}')::jsonb, | ||||||||||
| '{review,min_confidence}', | ||||||||||
| '0'::jsonb, | ||||||||||
| true | ||||||||||
| )::text | ||||||||||
| ) | ||||||||||
| WHERE parsed_json IS NOT NULL | ||||||||||
| AND ((parsed_json #>> '{}')::jsonb #>> '{review,min_confidence}') IS NOT NULL | ||||||||||
| AND ((parsed_json #>> '{}')::jsonb #>> '{review,min_confidence}')::numeric <> 0; | ||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| ALTER TABLE review_comments ADD COLUMN IF NOT EXISTS fingerprint_v2 TEXT; | ||
| ALTER TABLE comment_feedback ADD COLUMN IF NOT EXISTS fingerprint_v2 TEXT; | ||
|
|
||
| CREATE INDEX IF NOT EXISTS review_comments_posted_fingerprint_v2_idx | ||
| ON review_comments (file_review_id, fingerprint_v2) | ||
| WHERE posted AND fingerprint_v2 IS NOT NULL; | ||
|
|
||
| CREATE INDEX IF NOT EXISTS comment_feedback_repo_fingerprint_v2_idx | ||
| ON comment_feedback (repository_id, fingerprint_v2) | ||
| WHERE fingerprint_v2 IS NOT NULL; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| -- withheld_counts was written via JSON.stringify(), which postgres.js encodes as a jsonb STRING | ||
| -- scalar rather than an object. The TypeScript reader tolerated it, so the bug was invisible until a | ||
| -- SQL aggregate over the column returned zero for a review that had withheld five findings. | ||
| -- | ||
| -- Normalize the existing rows so the column has one shape and SQL can read it. Idempotent: rows that | ||
| -- are already objects are not matched. | ||
| UPDATE file_reviews | ||
| SET withheld_counts = (withheld_counts #>> '{}')::jsonb | ||
| WHERE withheld_counts IS NOT NULL | ||
| AND jsonb_typeof(withheld_counts) = 'string'; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| -- One jsonb encoding, everywhere. | ||
| -- | ||
| -- Migration 007 fixed file_reviews.withheld_counts, which was written via JSON.stringify() bound to a | ||
| -- `$n::jsonb` placeholder -- postgres.js types that as json and stores a jsonb STRING SCALAR, so every | ||
| -- SQL JSON operator silently reads nothing. The same bug was live at five more write sites, because | ||
| -- `parseJsonColumn` tolerates both shapes and therefore nothing ever broke loudly: | ||
| -- | ||
| -- repo_configs.parsed_json 11 rows -- forced 003 and 005 to branch around it | ||
| -- jobs.config_snapshot 204 rows | ||
| -- webhook_deliveries.payload 1,000 rows | ||
| -- repo_configs.fallback_models 0 rows -- all NULL today; write path was still wrong | ||
| -- repo_configs.size_overrides 0 rows | ||
| -- | ||
| -- The writers now bind `$n::text::jsonb`, which is correct for objects AND arrays (binding the raw | ||
| -- value is not: db/client.ts normalizeParam turns a JS array into a Postgres array literal, which | ||
| -- casts straight back to a string scalar). This normalizes the rows those writers already produced. | ||
| -- | ||
| -- Idempotent by construction: rows that are already objects or arrays fail the jsonb_typeof predicate. | ||
|
|
||
| UPDATE repo_configs SET parsed_json = (parsed_json #>> '{}')::jsonb | ||
| WHERE parsed_json IS NOT NULL AND jsonb_typeof(parsed_json) = 'string'; | ||
|
|
||
| UPDATE repo_configs SET fallback_models = (fallback_models #>> '{}')::jsonb | ||
| WHERE fallback_models IS NOT NULL AND jsonb_typeof(fallback_models) = 'string'; | ||
|
|
||
| UPDATE repo_configs SET size_overrides = (size_overrides #>> '{}')::jsonb | ||
| WHERE size_overrides IS NOT NULL AND jsonb_typeof(size_overrides) = 'string'; | ||
|
|
||
| UPDATE jobs SET config_snapshot = (config_snapshot #>> '{}')::jsonb | ||
| WHERE config_snapshot IS NOT NULL AND jsonb_typeof(config_snapshot) = 'string'; | ||
|
|
||
| UPDATE webhook_deliveries SET payload = (payload #>> '{}')::jsonb | ||
| WHERE payload IS NOT NULL AND jsonb_typeof(payload) = 'string'; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| -- The deterministic rule channel: a second finding source alongside the LLM. | ||
| -- | ||
| -- `source` defaults to 'llm', which backfills history correctly by construction -- every existing | ||
| -- row WAS model-generated -- so per-channel precision is computable over the whole corpus with no | ||
| -- data migration. Everything that counts findings must partition on it, or the numbers used to | ||
| -- judge the LLM channel silently include deterministic hits. | ||
| -- | ||
| -- `rule_id` is the retirement signal. A rule with many generated and no posted findings is one the | ||
| -- verifier always rejects: delete it or fix it, rather than leaving it to add noise. | ||
|
|
||
| ALTER TABLE review_comments ADD COLUMN IF NOT EXISTS source TEXT NOT NULL DEFAULT 'llm'; | ||
| ALTER TABLE review_comments ADD COLUMN IF NOT EXISTS rule_id TEXT; | ||
|
|
||
| -- Partial: rule findings are the rare case, and the queries that care are all "show me the non-LLM | ||
| -- ones". A full index would be almost entirely one repeated value. | ||
| CREATE INDEX IF NOT EXISTS review_comments_source_idx | ||
| ON review_comments (source) | ||
| WHERE source <> 'llm'; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| -- Google Vertex AI is a distinct api_format from 'gemini': Vertex rejects plain API keys and | ||
| -- requires an OAuth2 Bearer token minted from a service-account JSON key, so it needs its own | ||
| -- adapter and its own row in the enum. Widen the CHECK constraint to allow it. | ||
| ALTER TABLE llm_providers DROP CONSTRAINT IF EXISTS llm_providers_api_format_check; | ||
| ALTER TABLE llm_providers ADD CONSTRAINT llm_providers_api_format_check | ||
| CHECK (api_format IN ('openai', 'anthropic', 'gemini', 'cloudflare-workers-ai', 'vertex')); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,92 @@ | ||
| import js from '@eslint/js'; | ||
| import tseslint from 'typescript-eslint'; | ||
| import importX from 'eslint-plugin-import-x'; | ||
| import reactHooks from 'eslint-plugin-react-hooks'; | ||
| import { createTypeScriptImportResolver } from 'eslint-import-resolver-typescript'; | ||
|
|
||
| export default tseslint.config( | ||
| { | ||
| ignores: [ | ||
| 'dist/**', | ||
| 'node_modules/**', | ||
| // Recorded model responses and live re-run output: data, not source. | ||
| 'test/fixtures/**', | ||
| 'test/rerun/**', | ||
| // Generated by `wrangler types`. | ||
| 'src/server/worker-env.d.ts', | ||
| 'worker-configuration.d.ts', | ||
| ], | ||
| }, | ||
|
|
||
| js.configs.recommended, | ||
| ...tseslint.configs.recommended, | ||
|
|
||
| { | ||
| files: ['**/*.{ts,tsx,js,mjs}'], | ||
| plugins: { 'import-x': importX, 'react-hooks': reactHooks }, | ||
| settings: { | ||
| // The resolver has to understand the @server/@client/@shared aliases from tsconfig, or every | ||
| // internal import reads as unresolved and no-cycle/no-self-import are silently useless. | ||
| 'import-x/resolver-next': [ | ||
| createTypeScriptImportResolver({ project: './tsconfig.json' }), | ||
| ], | ||
| }, | ||
| rules: { | ||
| // TypeScript resolves every identifier already, and does it correctly for types, `declare`, | ||
| // and the Worker/DOM lib globals. Leaving this on means re-declaring hundreds of ambient | ||
| // globals in ESLint just to get a worse version of a check `npm run typecheck` already runs. | ||
| 'no-undef': 'off', | ||
|
|
||
| // The base rule cannot see TypeScript's type-only positions; the TS one can. | ||
| 'no-unused-vars': 'off', | ||
| '@typescript-eslint/no-unused-vars': ['error', { | ||
| // `catch {}` is the preferred form, but an unused binding is not worth an error. | ||
| caughtErrors: 'none', | ||
| argsIgnorePattern: '^_', | ||
| varsIgnorePattern: '^_', | ||
| }], | ||
|
|
||
| // `import-x/no-duplicates` and NOT the core `no-duplicate-imports`: the core rule is type-blind | ||
| // and flags the deliberate `import { Hono }` + `import type { Context }` split as a duplicate. | ||
| 'import-x/no-duplicates': 'error', | ||
| 'import-x/no-self-import': 'error', | ||
| 'import-x/no-cycle': 'error', | ||
|
|
||
| // An error, not a warning: the four places whose dependency array is deliberately narrower | ||
| // than their closure now carry a line-level disable stating why. A new violation should fail. | ||
| 'react-hooks/exhaustive-deps': 'error', | ||
|
|
||
| // Fires on the finding-title normalizer, which strips emoji and variation selectors from model | ||
| // output. Those combining characters are the point of it, and its behaviour is pinned by tests. | ||
| 'no-misleading-character-class': 'off', | ||
|
|
||
| // `any` is used deliberately at the provider and DB boundaries, where the shape is genuinely | ||
| // unknown until it is parsed. Turning this on would mean ~100 suppressions, not better types. | ||
| '@typescript-eslint/no-explicit-any': 'off', | ||
| }, | ||
| }, | ||
|
|
||
| { | ||
| files: ['src/client/**/*.{ts,tsx}'], | ||
| rules: { | ||
| 'react-hooks/rules-of-hooks': 'error', | ||
| }, | ||
| }, | ||
|
|
||
| { | ||
| // Plain-JS scripts are not covered by tsconfig, so they need their globals declared. | ||
| files: ['scripts/**/*.{js,mjs}'], | ||
| languageOptions: { | ||
| globals: { | ||
| console: 'readonly', | ||
| process: 'readonly', | ||
| Buffer: 'readonly', | ||
| fetch: 'readonly', | ||
| URL: 'readonly', | ||
| setTimeout: 'readonly', | ||
| clearTimeout: 'readonly', | ||
| __dirname: 'readonly', | ||
| }, | ||
| }, | ||
| }, | ||
| ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The 'cooldown' key is not a valid property within the 'updates' configuration block for Dependabot. Dependabot schema expects 'schedule' to define frequency, and there is no global or package-ecosystem level 'cooldown' parameter supported in the standard .github/dependabot.yml schema. This configuration will cause the Dependabot workflow to fail to parse the file.