Context: This plugin is for the Fivetran Connector SDK (CSDK). "CSDK" is shorthand for "Connector SDK".
Evaluate Connector
FIRST: Read sdk-reference.md from the plugin directory to load SDK rules and patterns.
Perform a static code evaluation of the connector. This is a read-only analysis — do NOT modify any files.
If no connector name is provided:
Ask which connector to evaluate. List any directories in the workspace that contain a connector.py file as options.
Step 1: Read Connector Code
Read all source files in the connector directory:
connector.py — required; main implementation
- Any other
.py files present
requirements.txt — if present, check for incorrectly declared pre-installed packages
Do NOT read or log any values from configuration.json.
If connector.py is missing, tell the user and stop.
Step 2: Evaluate
Analyze the code against the criteria below. Be deterministic and conservative — only flag issues with concrete code evidence. Do NOT flag theoretical or hypothetical problems.
CRITICAL SDK RULE — read before evaluating anything:
SDK operations (op.upsert, op.update, op.delete, op.checkpoint) must be called directly. They are NOT generators and must NEVER be used with yield or yield from.
- WRONG:
yield op.upsert(table="x", data=d)
- CORRECT:
op.upsert(table="x", data=d)
update() is a plain function, not a generator. yield from is only valid inside helper pagination functions that stream raw API records — it is never valid with SDK operations.
If you find code that calls SDK operations without yield, that is correct. Do not flag it.
REQUIRED Issues — Must Fix
Flag as required only when the code clearly demonstrates the problem.
1. Memory & Resource Management
- Entire dataset loaded into memory before processing (e.g., accumulating all records in a list before iterating)
- Files or connections opened without a context manager and without explicit
.close()
- Unbounded data structures that grow without limits
2. SDK Compliance
update(configuration, state) function must exist and be passed to Connector() instantiation
- At least one of
op.upsert(), op.update(), op.delete(), or op.truncate() must be called
op.checkpoint() must be called
- SDK operations (
op.upsert, op.update, op.delete, op.truncate, op.checkpoint) must be called directly — never with yield or yield from:
- WRONG:
yield op.upsert(table="x", data=d)
- CORRECT:
op.upsert(table="x", data=d)
update() must not return anything — SDK operations return None
- Schema: only
table, primary_key, columns keys are valid — any other key is an error
- Schema data types: if
columns are specified, only BOOLEAN, SHORT, INT, LONG, FLOAT, DOUBLE, DECIMAL, STRING, BINARY, JSON, XML, NAIVE_DATE, NAIVE_DATETIME, UTC_DATETIME are valid — any other type name is an error
- Declaring
columns with valid types is correct and supported — do NOT flag it as an issue. Declaring a primary_key for each table is recommended.
- Logging: preferred methods are
log.debug(), log.info(), log.warning(), log.error(), log.critical() — flag print(), logging.*, logger.* as required issues
- Type hints:
Generator[op.Operation, None, None] or any use of op.Operation in type hints is invalid — use plain dict and list only; never import from typing for SDK function signatures
exit() must never be used — use raise RuntimeError(...) instead
connector = Connector(...) must be at module (global) scope, not inside if __name__ == "__main__" or any function
3. Security
- Credentials, tokens, or secrets stored in the
state dict (state is persisted to disk unencrypted)
- Secrets or PII exposed in log messages (e.g.,
log.info(f"record: {data}"))
- Hardcoded credentials in source code
4. Data Reliability
- HTTP responses not validated — missing
raise_for_status() or equivalent status code check
- Infinite loops without a termination condition
- Missing pagination or streaming for API calls that return large datasets
- Cursor/state updated before processing the record (should be after):
- WRONG:
cursor = data['updated_at'] then op.upsert(...)
- CORRECT:
op.upsert(...) then cursor = data['updated_at']
5. Exception Handling
- Missing error handling around network, file, or database operations
- Exceptions caught but silently ignored (
except Exception: pass)
GOOD_TO_HAVE Issues — Suggestions
1. Performance
- HTTP requests missing a
timeout parameter
- Missing retry logic for transient network failures
2. Code Quality
- Functions over 50 lines without clear decomposition
- Missing input validation for required configuration keys
- Dead or duplicate code
requirements.txt lists requests or fivetran_connector_sdk — these are pre-installed in the runtime and must not be declared
- Schema declares a type for every column — declaring all columns forfeits the SDK's type inference and schema evolution. Prefer declaring types only where a specific type must be forced. (Declaring types for some columns is fine — do not flag that.)
- No
primary_key declared for a table — Fivetran will create a surrogate _fivetran_id key; declaring an explicit primary key is recommended
log.fine() or log.severe() used — these are deprecated Java-style aliases; prefer log.debug() and log.error() respectively
3. Reliability
- Retries without exponential backoff
- String timestamp comparison without datetime parsing (can fail across timezones)
- Pagination logic that could silently skip records
Do NOT Flag
- Code style or formatting preferences
- Theoretical edge cases not reachable in the actual execution path
- Issues already handled elsewhere in the code
- Cursor checkpoint placed after the loop when an empty page breaks before the cursor update — this is correct behavior
columns declared with valid data types — declaring types is explicitly supported by the SDK and useful for forcing a specific type. Only flag declaring a type for every column (good_to_have).
- Reading credentials from the
configuration dict — Fivetran encrypts configuration
- Any JSON-serializable value stored in state — all are valid
- Datetime string vs datetime object in
op.upsert() data — SDK accepts both
yield from inside a helper pagination generator that streams raw API records — this is correct and unrelated to SDK operations
log.fine() or log.severe() as a required issue — they are deprecated but still work; flag as good_to_have only
- Inline
ENCRYPTED:v1:<key_id>:local-fernet: values in configuration.json — this is normal; the plugin decrypts configuration values at runtime.
Step 3: Score
Start at 100 and deduct based on issues found:
Required deductions:
- Critical (security breach, data loss, SDK violation): −25 to −30 per issue
- Major (silent failures, memory exhaustion): −15 to −20 per issue
- Medium (reliability risk): −10 to −15 per issue
Good-to-have deductions:
- Significant omission: −3 to −5 per issue
- Minor suggestion: −1 to −2 per issue
Compute three subscores:
required_score: 100 minus required deductions
good_to_have_score: 100 minus good-to-have deductions
sdk_adherence_score: 100 minus SDK-specific violations only
Floor all scores at 0.
Step 4: Report
Present findings using this structure. Omit any section that has no issues.
## Evaluation Report — <connector_name>
### Score
Overall: <score>/100
- SDK Adherence: <sdk_adherence_score>/100
- Required: <required_score>/100
- Good to Have: <good_to_have_score>/100
### Required Issues
**[<tag>] <issue title>**
- Problem: <what is wrong>
- Location: <function name or line reference>
- Current code:
```python
<offending snippet>
Good to Have
Summary
<2–3 sentence overall assessment>
**Tags:** `memory management` | `security` | `resource management` | `reliability` | `exception handling` | `input validation` | `configurability` | `code quality` | `sdk compliance` | `others`
If no issues are found in a category, write `None found.`
Do NOT suggest fixes for `good_to_have` issues unless the fix is a straightforward one-liner. Do NOT modify any files.
1---2name: evaluate-connector-23description: Evaluate a Fivetran connector for correctness, SDK compliance, security, and reliability. Use when the user wants a code review or quality report before deploying.4---56> **Context**: This plugin is for the Fivetran Connector SDK (CSDK). "CSDK" is shorthand for "Connector SDK".78# Evaluate Connector910**FIRST**: Read `sdk-reference.md` from the plugin directory to load SDK rules and patterns.1112Perform a static code evaluation of the connector. This is a read-only analysis — do NOT modify any files.1314**If no connector name is provided:**15Ask which connector to evaluate. List any directories in the workspace that contain a `connector.py` file as options.1617## Step 1: Read Connector Code1819Read all source files in the connector directory:20- `connector.py` — required; main implementation21- Any other `.py` files present22- `requirements.txt` — if present, check for incorrectly declared pre-installed packages2324Do NOT read or log any values from `configuration.json`.2526If `connector.py` is missing, tell the user and stop.2728## Step 2: Evaluate2930Analyze the code against the criteria below. Be deterministic and conservative — only flag issues with concrete code evidence. Do NOT flag theoretical or hypothetical problems.3132---3334> **CRITICAL SDK RULE — read before evaluating anything:**35> SDK operations (`op.upsert`, `op.update`, `op.delete`, `op.checkpoint`) must be called **directly**. They are NOT generators and must NEVER be used with `yield` or `yield from`.36> - WRONG: `yield op.upsert(table="x", data=d)`37> - CORRECT: `op.upsert(table="x", data=d)`38>39> `update()` is a plain function, not a generator. `yield from` is only valid inside helper pagination functions that stream raw API records — it is never valid with SDK operations.40>41> If you find code that calls SDK operations without `yield`, that is **correct**. Do not flag it.4243---4445### REQUIRED Issues — Must Fix4647Flag as `required` only when the code clearly demonstrates the problem.4849**1. Memory & Resource Management**50- Entire dataset loaded into memory before processing (e.g., accumulating all records in a list before iterating)51- Files or connections opened without a context manager and without explicit `.close()`52- Unbounded data structures that grow without limits5354**2. SDK Compliance**55- `update(configuration, state)` function must exist and be passed to `Connector()` instantiation56- At least one of `op.upsert()`, `op.update()`, `op.delete()`, or `op.truncate()` must be called57- `op.checkpoint()` must be called58- SDK operations (`op.upsert`, `op.update`, `op.delete`, `op.truncate`, `op.checkpoint`) must be called directly — never with `yield` or `yield from`:59 - WRONG: `yield op.upsert(table="x", data=d)`60 - CORRECT: `op.upsert(table="x", data=d)`61- `update()` must not return anything — SDK operations return `None`62- Schema: only `table`, `primary_key`, `columns` keys are valid — any other key is an error63- Schema data types: if `columns` are specified, only `BOOLEAN`, `SHORT`, `INT`, `LONG`, `FLOAT`, `DOUBLE`, `DECIMAL`, `STRING`, `BINARY`, `JSON`, `XML`, `NAIVE_DATE`, `NAIVE_DATETIME`, `UTC_DATETIME` are valid — any other type name is an error64- Declaring `columns` with valid types is **correct and supported** — do NOT flag it as an issue. Declaring a `primary_key` for each table is recommended.65- Logging: preferred methods are `log.debug()`, `log.info()`, `log.warning()`, `log.error()`, `log.critical()` — flag `print()`, `logging.*`, `logger.*` as required issues66- Type hints: `Generator[op.Operation, None, None]` or any use of `op.Operation` in type hints is invalid — use plain `dict` and `list` only; never import from `typing` for SDK function signatures67- `exit()` must never be used — use `raise RuntimeError(...)` instead68- `connector = Connector(...)` must be at module (global) scope, not inside `if __name__ == "__main__"` or any function6970**3. Security**71- Credentials, tokens, or secrets stored in the `state` dict (state is persisted to disk unencrypted)72- Secrets or PII exposed in log messages (e.g., `log.info(f"record: {data}")`)73- Hardcoded credentials in source code7475**4. Data Reliability**76- HTTP responses not validated — missing `raise_for_status()` or equivalent status code check77- Infinite loops without a termination condition78- Missing pagination or streaming for API calls that return large datasets79- Cursor/state updated **before** processing the record (should be after):80 - WRONG: `cursor = data['updated_at']` then `op.upsert(...)`81 - CORRECT: `op.upsert(...)` then `cursor = data['updated_at']`8283**5. Exception Handling**84- Missing error handling around network, file, or database operations85- Exceptions caught but silently ignored (`except Exception: pass`)8687---8889### GOOD_TO_HAVE Issues — Suggestions9091**1. Performance**92- HTTP requests missing a `timeout` parameter93- Missing retry logic for transient network failures9495**2. Code Quality**96- Functions over 50 lines without clear decomposition97- Missing input validation for required configuration keys98- Dead or duplicate code99- `requirements.txt` lists `requests` or `fivetran_connector_sdk` — these are pre-installed in the runtime and must not be declared100- Schema declares a type for **every** column — declaring all columns forfeits the SDK's type inference and schema evolution. Prefer declaring types only where a specific type must be forced. (Declaring types for *some* columns is fine — do not flag that.)101- No `primary_key` declared for a table — Fivetran will create a surrogate `_fivetran_id` key; declaring an explicit primary key is recommended102- `log.fine()` or `log.severe()` used — these are deprecated Java-style aliases; prefer `log.debug()` and `log.error()` respectively103104**3. Reliability**105- Retries without exponential backoff106- String timestamp comparison without datetime parsing (can fail across timezones)107- Pagination logic that could silently skip records108109---110111### Do NOT Flag112- Code style or formatting preferences113- Theoretical edge cases not reachable in the actual execution path114- Issues already handled elsewhere in the code115- Cursor checkpoint placed after the loop when an empty page breaks before the cursor update — this is correct behavior116- `columns` declared with valid data types — declaring types is explicitly supported by the SDK and useful for forcing a specific type. Only flag declaring a type for *every* column (good_to_have).117- Reading credentials from the `configuration` dict — Fivetran encrypts configuration118- Any JSON-serializable value stored in state — all are valid119- Datetime string vs datetime object in `op.upsert()` data — SDK accepts both120- `yield from` inside a helper pagination generator that streams raw API records — this is correct and unrelated to SDK operations121- `log.fine()` or `log.severe()` as a required issue — they are deprecated but still work; flag as good_to_have only122- Inline `ENCRYPTED:v1:<key_id>:local-fernet:` values in `configuration.json` — this is normal; the plugin decrypts configuration values at runtime.123124---125126## Step 3: Score127128Start at 100 and deduct based on issues found:129130**Required deductions:**131- Critical (security breach, data loss, SDK violation): −25 to −30 per issue132- Major (silent failures, memory exhaustion): −15 to −20 per issue133- Medium (reliability risk): −10 to −15 per issue134135**Good-to-have deductions:**136- Significant omission: −3 to −5 per issue137- Minor suggestion: −1 to −2 per issue138139Compute three subscores:140- `required_score`: 100 minus required deductions141- `good_to_have_score`: 100 minus good-to-have deductions142- `sdk_adherence_score`: 100 minus SDK-specific violations only143144Floor all scores at 0.145146---147148## Step 4: Report149150Present findings using this structure. Omit any section that has no issues.151152```153## Evaluation Report — <connector_name>154155### Score156Overall: <score>/100157- SDK Adherence: <sdk_adherence_score>/100158- Required: <required_score>/100159- Good to Have: <good_to_have_score>/100160161### Required Issues162**[<tag>] <issue title>**163- Problem: <what is wrong>164- Location: <function name or line reference>165- Current code:166 ```python167 <offending snippet>168 ```169- Fix:170 ```python171 <corrected snippet>172 ```173174### Good to Have175<same structure as above>176177### Summary178<2–3 sentence overall assessment>179```180181**Tags:** `memory management` | `security` | `resource management` | `reliability` | `exception handling` | `input validation` | `configurability` | `code quality` | `sdk compliance` | `others`182183If no issues are found in a category, write `None found.`184185Do NOT suggest fixes for `good_to_have` issues unless the fix is a straightforward one-liner. Do NOT modify any files.