agentleFS
giantswarmgiantswarm/muster/.cursor/rules/architecture.mdc

muster / rules

Cursor rule40 starsChanged 10 months agoApache-2.0View on GitHub

- Define Interface in API: Add a new handler interface to internal/api/handlers.go. - Implement Adapter in Service Package: In the package providing the functionality (e.g., internal/myservice), create an api_adapter.go. This adapter implements the interface and calls the package's internal logic. - Register the Adapter: Implement a Register() method on the adapter that calls the registration function in the api package. - Consume via API: Any other package that needs to use the service MUST retrieve the handler from the api…

  • Installs packages

The file

We split this architecture.mdc into the rules it gives an agent

10 rules. About 0 are common, 5 are distinctive, and 5 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈5

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 5

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    One-Way Dependency: All packages can depend on internal/api, but internal/api depends on no other package in the project.

    line 15
  2. Very specific:

    Add a new handler interface to internal/api/handlers.go.

    line 18
  3. Very specific:

    Make sure muster is up to date: Run go build -o ./muster .

    line 73
  4. Distinctive:

    Minimum Coverage: All new code MUST achieve at least 80% unit test coverage.

    line 81
  5. Distinctive:

    Formatting: Before every commit, run:

    line 85
  6. Very specific:

    Dependencies: Before adding a new dependency with go get, use web_search to find its latest stable version.

    line 90
  7. Distinctive:

    File Size: Keep files focused and under 400 lines.

    line 92
  8. Distinctive:

    Commit & Push & Pull Request: Check the github workflow

    line 99
  9. Very specific:

    Packages: Every package MUST have a doc.go file explaining its purpose.

    line 102
  10. Distinctive:

    Exported Members: Every exported function, type, and variable MUST have a GoDoc comment.

    line 103

≈ “Common” is an estimate: at least 1 in 5 of the 6,668 Cursor rule files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
architecture.mdc
---
description:
globs:
alwaysApply: true
---
- **Architectural principles**
  - This document outlines the fundamental architectural principles and patterns for the `muster` codebase. Adherence to these guidelines is **mandatory** to maintain a clean, decoupled, and testable system.

- **The API Service Locator Pattern**
  - **All inter-package communication MUST go through the central API layer.** This is the most critical rule in our architecture. It prevents direct coupling between packages, enabling them to be developed, tested, and refactored independently.

- **Core Concepts**
  - **Central API:** The `internal/api` package acts as a service locator. It contains handlers for all core muster functionality and also the tool definitions exposed by the aggregator package.
  - **Interface-Driven:** Packages communicate using interfaces defined in `internal/api/handlers.go`. They do not know about each other's concrete implementations.
  - **One-Way Dependency:** All packages can depend on `internal/api`, but `internal/api` depends on **no other package** in the project. This is crucial for preventing circular dependencies.

- **Define Interface in API:**
  Add a new handler interface to `internal/api/handlers.go`.
  ```go
  // internal/api/handlers.go
  type MyServiceHandler interface {
      DoSomething(ctx context.Context) error
  }
  ```
- **Implement Adapter in Service Package:**
  In the package providing the functionality (e.g., `internal/myservice`), create an `api_adapter.go`. This adapter implements the interface and calls the package's internal logic.
  ```go
  // internal/myservice/api_adapter.go
  type Adapter struct {
      logic *ServiceLogic
  }
  func (a *Adapter) DoSomething(ctx context.Context) error {
      return a.logic.performAction(ctx)
  }
  ```
- **Register the Adapter:**
  Implement a `Register()` method on the adapter that calls the registration function in the `api` package.
  ```go
  // internal/myservice/api_adapter.go
  func (a *Adapter) Register() {
      api.RegisterMyService(a)
  }
  ```
- **Consume via API:**
  Any other package that needs to use the service **MUST** retrieve the handler from the `api` package. It **MUST NOT** import the service package directly.
  ```go
  // in another_package/logic.go
  import "github.com/giantswarm/muster/v5/internal/api"

  func DoWork(ctx context.Context) {
      handler := api.GetMyService()
      if handler == nil {
          // Handle case where service is not available
          return
      }
      handler.DoSomething(ctx)
  }
  ```

- **Workflow executions**
  - From the user perspective workflows are executed via the tools `workflow_<workflow-name>`.
  - In the workflows and api package these workflow execution tools are still called `action_<workflow-name>`.
  - The aggregator maps the `action_<workflow-name>` tools to the actual `workflow_<workflow-name>`.

- **CRITICAL: Anti-Patterns**
  -   **NEVER import workflow, mcpserver, serviceclass and service packages directly.** This creates tight coupling and violates the core architectural principle.
  -   **NEVER USE TIMER/SLEEP/WAIT TO FIX TESTS OR RACE CONDITIONS. NEVER!!**
  -   **ALWAYS retrieve handlers from the `api` package.**
  -   **Don't change schema.json manually** It is generated via `muster test --generate-schema` and changes are the result of the actual api of `muster serve`.

- **BDD test scenarios**
  - **Execute test scenarios like this**: `./muster test --scenario <scenario> --verbose`
  - **Make sure muster is up to date**: Run `go build -o ./muster .` and use `./muster` from the worktree (never `go install`: it overwrites the shared `~/.go/bin/muster`)
  - **Always rebuild `./muster` after a code change in go**
  - **There is no need to start muster serve**: Each test scenario is executed in its own environment and its own instance of `muster serve`
  - **Always treat the scenario as the defined and supposed user behavior**: If a scenario fails it is most likely a regression and the code needs to be fixed and not the scenario.
  - **To see debug messages during test scenario execution**: You need to add a `--debug` flag: `./muster test --scenario <scenario> --verbose --debug`
  - **Never ever stop or commit with failing test scenarios**: You must fix them.

- **Testing Standards**
  - **Minimum Coverage:** All new code **MUST** achieve at least **80% unit test coverage**.
  - **No Flaky Tests:** Tests **MUST** be deterministic. Do not use `time.Sleep` or other mechanisms that can lead to race conditions. Use dependency injection for things like clocks or timers to make code testable.

- **Go Development & Style**
  - **Formatting:** Before **every commit**, run:
    ```bash
    goimports -w .
    go fmt ./...
    ```
  - **Dependencies:** Before adding a new dependency with `go get`, use `web_search` to find its latest stable version.
  - **Error Handling:** Wrap errors with `fmt.Errorf("context: %w", err)` to preserve context.
  - **File Size:** Keep files focused and under **400 lines**. Refactor larger files.

- **When ever you get a "Finish this up":**
  - **Run the tests:** `make test`
  - **Rebuild the binary:** `go build -o ./muster .`
  - **Run the scenarios:** `./muster test --parallel 50`
  - **Format the code:** `goimports -w . && go fmt ./...`
  - **Commit & Push & Pull Request**: Check the github workflow

- **Documentation**
  - **Packages:** Every package **MUST** have a `doc.go` file explaining its purpose.
  - **Exported Members:** Every exported function, type, and variable **MUST** have a GoDoc comment.
  - **Project Docs:** New features or significant changes require updates to the relevant documents in the `docs/` directory.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.