Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 32 additions & 10 deletions .cursor/rules/cursor/rules.mdc
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# (C) 2025 GoodData Corporation
---
description: How to create or update Cursor rule files - minimal templates and standards
description: How to create or update Cursor rule files - includes minimal templates and standards
alwaysApply: false
---

Expand All @@ -10,19 +11,21 @@ alwaysApply: false
- `.cursor/rules/general/` - General rules (always applied)
- `.cursor/rules/packages/` - Package-specific rules
- `.cursor/rules/technologies/` - Technology rules (Python, testing)
- `.cursor/rules/guides/shared/` - Shared conventions (commits, etc.)
- `.cursor/rules/cursor/` - Cursor workflow and meta-rules

## Rule Creation Process

1. **Ask for clarification** if codebase location unclear
1. **Ask for clarification** if codebase location is unclear
2. **Investigate the codebase** relevant to the rule
3. **Look at similar existing rules** as examples (better than templates)
4. **Keep it minimal** - target 25-40 lines max
5. **Focus on proprietary knowledge** - not generic patterns
6. **Remove anything that doesn't help Cursor** - do not put anything that doesn't help Cursor into any rule file

## Updating Existing Rules

**CRITICAL**: Be MINIMAL. Add only what prevents actual errors.
**CRITICAL**: When asked to extend rules, be MINIMAL. Add only what prevents actual errors.

**DO (Minimal):**
```python
Expand All @@ -42,23 +45,42 @@ if TYPE_CHECKING:
- ❌ Step-by-step tutorials
- ❌ Verbose "correct vs wrong" comparisons

**Rule of thumb**: If it didn't cause a validation error, don't add it.
**Rule of thumb**: If it didn't cause a validation error, don't add it to the rule.

**Target length**: 25-40 lines. If over 50 lines, too verbose.
**Target length**: 25-40 lines. If over 50 lines, you're being too verbose.

## Rule Structure
## Rule Structure (All Types)

**Essential sections:**
- Description header (1 line)
- Owns / Does NOT Own (clear boundaries)
- Critical constraints (if any)
- Dependencies
- Critical constraints or anti-patterns (if any)
- Dependencies (required rules to load together)

**Optional sections:**
- Integration (only if complex)
- Proprietary patterns (only if non-obvious)
- Essential commands (only if unique to this package)

## Quality Criteria

**Good rule (25-40 lines):**
- ✅ Only proprietary/non-obvious knowledge
- ✅ Clear package boundaries
- ✅ Points to READMEs for details
- ✅ Copy-paste ready patterns (minimal examples)

**Bad rule (>50 lines):**
- ❌ Generic technology descriptions
- ❌ Long explanations or tutorials
- ❌ Verbose examples with commentary
- ❌ Information already in code/docs

## Rule Header Format

```markdown
---
description: {Brief - used by Cursor for rule selection}
alwaysApply: false # (true only for general rules)
description: {Brief but complete - used by Cursor for rule selection}
alwaysApply: false # (or true only for general rules)
---
```
13 changes: 10 additions & 3 deletions .cursor/rules/cursor/workflow-validation.mdc
Original file line number Diff line number Diff line change
@@ -1,19 +1,26 @@
# (C) 2025 GoodData Corporation
---
description: Cursor IDE workflow validation and rule management
alwaysApply: true
---

# Cursor IDE Workflow Validation

## Workflow Constraints
## Workflow and output constraints

- Include all rules related to the user question; if rules mention dependencies, include those too.
- After fully answering, report the list of used rules.
- Example: **Used rules**: general/general, technologies/python, packages/gooddata-sdk
- Do not print rule previews or long plans.
- Keep status updates to one short sentence.
- Never inline full rule contents; reference by rule path only when needed.
- Only list rule IDs in "Used rules:".

## Rule Search
## Rule Search Requirements

Always look for relevant cursor rules based on the character of changes.
Always look for relevant cursor rules in this repository based on the character of the changes.
Do not inline rule contents; reference rules by path only when necessary.

## Git Commit Requirements

Follow commit message format from `guides/shared/commits.mdc`.
43 changes: 29 additions & 14 deletions .cursor/rules/general/general.mdc
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
# (C) 2025 GoodData Corporation
---
alwaysApply: true
---

# GoodData Python SDK Coding Guidelines

Applies to all packages and code in this Python SDK workspace.
Think in steps before changes. Search for relevant cursor rules based on the character of changes.
Think in steps before changes. Always search for relevant cursor rules based on the character of changes.

## Core Principles

Expand All @@ -15,11 +16,17 @@ Think in steps before changes. Search for relevant cursor rules based on the cha

## ⚠️ CRITICAL: AI Behavior Rules - ALWAYS ENFORCE

**NO AUTO-IMPLEMENTATION**:
**NO AUTO-IMPLEMENTATION**:
- Do not generate, rename or refactor what is not explicitly requested
- Do not generate code changes unless user explicitly asks for it
- NEVER create summary/documentation markdown files unless explicitly requested
- NEVER create summary/documentation markdown files unless user explicitly requests it
- NEVER update rule files for code issues - fix the code instead
- Break complex tasks into smaller deliverable units

**Documentation Quality**:
- NEVER reference specific line numbers (e.g., "lines 45-340", "~line 60") in documentation or Cursor rules
- Use descriptive structural locations instead (e.g., "in the outputs section", "at the top of the file")

**For complex tasks**:
1. Implement ONLY the first task, then STOP
2. Ask permission to continue, offering: (a) next task only, or (b) all remaining tasks
Expand All @@ -28,20 +35,23 @@ Think in steps before changes. Search for relevant cursor rules based on the cha

## Code Validation

**If gdc-ruler MCP server is available**: Use `validate_python` tool with this workspace path.
```
validate_python(path=".") # From workspace root
```

**Otherwise**: Run manually:
**MANDATORY after code changes**: Run validation from workspace root:
```bash
make format-fix && make mypy && make test
make format-fix && make lint && make mypy && make test
```

**⚠️ CRITICAL: Do NOT use `read_lints` tool**:
- `read_lints` is incompatible with our custom linting - it will fail
- Use manual validation commands above

**Scoped testing**: `TEST_ENVS=py312 ADD_ARGS="-k test_name" make test`

See `technologies/testing` rule for VCR cassette workflow.

## Testing Practices

**Extend existing tests, don't create new ones**: When making incremental changes (new property, enum value, field), add to existing test fixtures rather than creating new tests.

## Package Structure

**Workspace packages** (in `packages/`):
Expand All @@ -61,10 +71,15 @@ See `technologies/testing` rule for VCR cassette workflow.

## OpenAPI Client Generation

**DO NOT manually edit** generated client code in `gooddata-*-client/` directories.
**DO NOT manually edit** generated client code in `gooddata-api-client/` directories.

To regenerate: `make api-client`

See `.openapi-generator/README.md` for regeneration instructions.
## Library Integration

## Fast-Changing Dependencies
**Hierarchy** (combat outdated LLM knowledge):
1. **Internal GoodData packages** - ALWAYS preferred
2. **Approved stable libraries** - Use versions from pyproject.toml
3. **New/unknown libraries** - MANDATORY: web search for current docs/APIs before suggesting

**When suggesting third-party libraries**: Verify current APIs, prefer established libraries, check Python 3.10+ compatibility.
When suggesting third-party libraries: verify current APIs, prefer established libraries, explicitly state uncertainty.
70 changes: 70 additions & 0 deletions .cursor/rules/guides/shared/commits.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# (C) 2025 GoodData Corporation
---
description: Git commit conventions - conventional commits format
alwaysApply: false
---

# Commit Conventions

Commits must follow the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0) specification.

## Format

```
<type>(<scope>): <description>

<body>

jira: <ticket-number>
risk: <risk-flag>
```

## Type

Must be one of:
- `feat` - A new feature
- `fix` - A bug fix
- `build` - Changes to build system or dependencies
- `ci` - Changes to CI configuration
- `docs` - Documentation changes
- `perf` - Performance improvements
- `style` - Formatting changes (no code change)
- `refactor` - Code change that neither fixes a bug nor adds a feature
- `test` - Adding or correcting tests
- `chore` - Other changes that don't modify src or test files
- `revert` - Revert previous changes

## Scope

Optional. The affected package name (e.g., `gooddata-sdk`, `gooddata-pandas`, `gooddata-dbt`).

## Description

- Max 50 characters (full line ≤ 70 chars)
- Lowercase, imperative mood
- No period at end

## Body

Optional detailed explanation. Wrap lines at 72 characters.

## Footer (Required)

- `jira: PROJECT-ID` or `jira: trivial` for minor changes
- `risk: nonprod|low|high`

## Example

```
feat(gooddata-sdk): add workspace permission methods

Add new methods to catalog_permission service for managing
workspace-level permissions programmatically.

jira: RAIL-12345
risk: low
```

## Dependencies

Related: general/general
6 changes: 6 additions & 0 deletions .cursor/rules/packages/gooddata-pandas.mdc
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# (C) 2025 GoodData Corporation
---
description: GoodData Pandas package - pandas integration layer for GoodData SDK
alwaysApply: false
Expand All @@ -15,6 +16,7 @@ alwaysApply: false
## Does NOT Own

- Core SDK functionality → gooddata-sdk package
- API client → gooddata-api-client (generated)

## Architecture

Expand All @@ -31,6 +33,10 @@ gp = GoodPandas(host="https://example.gooddata.com", token="...")
df = gp.data_frames(workspace_id="demo", insight_id="...")
```

## Testing

Uses vcrpy cassettes. See `technologies/testing` rule for workflow.

## Dependencies

Required: technologies/python, packages/gooddata-sdk
Expand Down
3 changes: 3 additions & 0 deletions .cursor/rules/packages/gooddata-sdk.mdc
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# (C) 2025 GoodData Corporation
---
description: GoodData SDK core package - primary interface for GoodData Cloud
alwaysApply: false
Expand Down Expand Up @@ -42,6 +43,8 @@ workspaces = sdk.catalog_workspace.list_workspaces()

Uses vcrpy cassettes. See `technologies/testing` rule for workflow.

**Extend existing tests** when adding new functionality - don't create new test files for minor changes.

## Dependencies

Required: technologies/python, technologies/testing
Expand Down
57 changes: 31 additions & 26 deletions .cursor/rules/technologies/python.mdc
Original file line number Diff line number Diff line change
@@ -1,48 +1,53 @@
# (C) 2025 GoodData Corporation
---
description: Python development - mypy-clean code patterns
description: Python development - mypy-clean code patterns and typing
alwaysApply: false
---

# Python Development
# Python Development Guidelines

**Goal:** Ship mypy-clean code on first pass. No "write → validate → fix" loops.

**Supported versions**: Python 3.10 and higher

## Imports

**Absolute imports only.** Relative imports break monorepo navigation.
**Use absolute imports only.** Relative imports break IDE navigation.
```python
from gooddata_sdk.client import GoodDataSdk # ✅
from .client import GoodDataSdk # ❌
```

**All imports at top of file.** After docstring and `from __future__ import annotations`.

## Type-first Habits
**All imports must be at the top of the file.** Never import modules inside functions or in the middle of code. All `import` and `from ... import` statements must be placed at the top of the file, after the module docstring and `from __future__ import annotations` if present.

## Type-first habits
- Every def + local (esp empty list/dict/set) annotated; dataclasses fully typed.
- Use `from __future__ import annotations` for forward references.
- Guard external data (YAML/JSON) as `Any` then narrow types.

## External Data (YAML/JSON)

```python
raw = yaml.safe_load(handle)
if not isinstance(raw, dict):
raise ValueError("expected mapping")
cfg: dict[str, object] = {str(k): v for k, v in raw.items()}
```

## Casts / Guards

- Single authoritative `cast(...)` + reuse variable
- Guard pattern: `if isinstance(mode_raw, str): mode = mode_raw else: raise ValueError("...")`
- `typing.assert_never` for exhaustive branches

## Validation flow (If MCP server installed)
- Python-only chores: `validate_python(path)` (format, lint, types, test).
- Mixed stacks: run Python + Kotlin validators separately; skip umbrella `validate` until new classifier routing lands.
- Helpers when default mutable needed:
```python
def _new_set() -> set[str]:
return set()
```

## External data (YAML/JSON/etc.)
- Treat loader output as `Any`; guard then normalize keys:
```python
raw = yaml.safe_load(handle)
if not isinstance(raw, dict):
raise ValueError("expected mapping")
cfg: dict[str, object] = {str(k): v for k, v in raw.items()}
```
- Narrow collections once: `entries = [x for x in cast(list[object], cfg.get("items", [])) if isinstance(x, str)]`.
- Prefer `TypedDict`/dataclass when schema known.

## Logging & diagnostics
- Never log raw `Any`; cast or pre-format (`logger.warning("… %r", safe)`).
- Avoid redundant `isinstance` after data narrowed; mypy flags it.

## Casts / guards
- Single authoritative `cast(...)` + reuse variable.
- Guard pattern: `if isinstance(mode_raw, str): mode = mode_raw else: raise ValueError("mode str")`.
- `typing.assert_never` for exhaustive branches.

## Documentation

Expand Down
Loading
Loading