Skip to content

feat(repo): Add new modes#315

Open
pedronauck wants to merge 32 commits intomainfrom
pn/modes
Open

feat(repo): Add new modes#315
pedronauck wants to merge 32 commits intomainfrom
pn/modes

Conversation

@pedronauck
Copy link
Copy Markdown
Member

@pedronauck pedronauck commented Oct 31, 2025

Summary by CodeRabbit

  • New Features

    • Added three deployment modes: memory, persistent, and distributed; new --mode CLI flag and mode shown in project/init flows (default: memory).
    • Mode-aware project generation: templates now produce mode-specific files, README content, env examples, and Docker inclusion.
  • Documentation

    • Updated generated READMEs, env examples, and API docs with mode-specific guidance and clearer error/help text.
  • Tests

    • Broadened tests to validate all modes and multi-driver setups.

@pedronauck pedronauck self-assigned this Oct 31, 2025
@vercel
Copy link
Copy Markdown

vercel Bot commented Oct 31, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
compozy-docs Ready Ready Preview Comment Nov 1, 2025 0:05am

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Oct 31, 2025

Walkthrough

Refactors deployment modes from a single "standalone" option into three modes: "memory" (in-memory SQLite with embedded services), "persistent" (file-backed SQLite with embedded services), and "distributed" (external services). Propagates mode through config, CLI, templates, infra initialization, and extensive tests.

Changes

Cohort / File(s) Summary
Configuration Core & Schema
pkg/config/config.go, pkg/config/resolver.go, pkg/config/definition/schema.go
Added ModeMemory/ModePersistent/ModeDistributed, introduced isEmbeddedMode(), renamed standalone → embedded types (StandaloneConfig → EmbeddedTemporalConfig, RedisStandaloneConfig → EmbeddedRedisConfig), added global mode field and registry wiring, updated env prefixes and defaults.
Validation & Loader Tests
pkg/config/loader.go, pkg/config/loader_test.go, pkg/config/config_test.go, pkg/config/resolver_test.go
Reworked mode validation (deprecated standalone), friendly validation errors, validateMCPProxyMode, table-driven tests covering inheritance/port requirements and mode permutations.
CLI: init & start
cli/cmd/init/init.go, cli/cmd/init/components/project_form.go, cli/cmd/start/start.go, cli/cmd/start/start_test.go
Added Mode to Options and interactive form, --mode flag, mode validation/defaulting, propagate Mode into GenerateOptions, updated start mode validation and tests (memory/persistent/distributed).
CLI: config & flags
cli/cmd/config/config_test.go, cli/helpers/flag_categories.go
Updated golden references (standalone→memory), added mode to core flags category.
Template types & generation
pkg/template/types.go, pkg/template/types_test.go, pkg/template/service.go, pkg/template/generator.go
Added DefaultMode, validModes, ValidateMode, GenerateOptions.Mode and Context, logging around mode-driven generation, validation and defaults in template service.
Basic template files & tests
pkg/template/templates/basic/basic.go, pkg/template/templates/basic/basic_test.go, pkg/template/templates/basic/README.md.tmpl, pkg/template/templates/basic/compozy.yaml.tmpl, pkg/template/templates/basic/env.example.tmpl, pkg/template/templates/basic/gitignore.tmpl
Propagated Mode into projectConfig and template rendering; mode-aware conditional blocks added across README, compozy.yaml, env.example, gitignore; tests verifying mode-specific artifacts and Docker inclusion.
Infrastructure: cache & miniredis
engine/infra/cache/mod.go, engine/infra/cache/mod_test.go, engine/infra/cache/miniredis_embedded.go, engine/infra/cache/miniredis_embedded_test.go, engine/infra/cache/snapshot_manager_test.go
Replaced "standalone" embedded Redis type with MiniredisEmbedded, added memory/persistent handlers and default persistence dir, updated tests to cover memory/persistent/distributed behaviors.
Infrastructure: server, MCP, temporal wiring
engine/infra/server/dependencies.go, engine/infra/server/dependencies_test.go, engine/infra/server/server.go, engine/infra/server/mcp.go, engine/infra/server/mcp_test.go, engine/infra/server/temporal_resolver_test.go
Renamed standalone→embedded Temporal helpers, compute embedded DB file per mode, log runtime mode and effective settings, updated MCP embedding logic to use embedded modes, adjusted related tests and messages.
Infrastructure: DB migrations & task repos
engine/infra/postgres/migrations.go, engine/infra/sqlite/migrations.go, engine/infra/sqlite/migrations/20250603124915_create_task_states.sql, engine/infra/postgres/taskrepo.go, engine/infra/sqlite/taskrepo.go
Serialized migrations with mutex, expanded execution_type allowed values, added defaultExecutionType helper, introduced qualified column set for recursive queries.
Embedded worker & namespace
engine/worker/embedded/config.go, engine/worker/embedded/namespace.go, engine/worker/embedded/namespace_test.go
Aliased embedded Config to canonical EmbeddedTemporalConfig, added SQLite schema pre-init with "already exists" handling, updated test namespace defaults.
Task runner
engine/task/exec/runner.go
Added resources.ResourceStore field to Runner and validateRunner pre-check used in Prepare.
Template generator README/docs updates
pkg/template/templates/basic/README.md.tmpl, pkg/template/templates/basic/env.example.tmpl
Added mode-specific instructions and env examples; moved/condensed provider keys and runtime envs.
Test infra: multi-mode DB helpers & repos
test/helpers/database.go, test/helpers/database_test.go, test/helpers/repo.go, test/helpers/server/server.go
New SetupDatabaseWithMode and helpers for SQLite (in-memory/persistent) and Postgres container paths; SetupTestDatabase variadic driver; replaced Postgres pool usage with repo.Provider for tests and updated harness.
Integration tests & helpers
test/integration/cache/adapter_contract_test.go, test/integration/database/multi_driver_test.go, test/integration/repo/repo_test_helpers.go, test/integration/repo/task_test.go, test/integration/repo/workflow_test.go, test/integration/store/operations_test.go, test/integration/server/executions_integration_test.go, test/integration/server/mcp_health_test.go, test/integration/tasks/helpers/setup.go, test/integration/tasks/core/concurrent_test.go, test/integration/tasks/basic/response_handler_test.go
Shifted many tests from shared Postgres to mode-driven setup (SQLite by default), provider-based repo factories, removed explicit table truncation, added driver-parametrized test setup helpers and adjusted tests to memory/persistent/distributed modes.
Examples & docs
examples/memory-mode/.env.example, examples/persistent-mode/.env.example, examples/distributed-mode/.env.example, examples/memory-mode/api.http, examples/memory-mode/edge-deployment/Dockerfile.edge, examples/standalone/.env.example, docs/docs.go
Added memory/persistent/distributed example envs and adjusted API example labels; updated API docs 503 descriptions and SSE route notes.
Small API docs & comments
engine/agent/router/stream.go, engine/task/router/stream.go, engine/workflow/router/stream.go, engine/tool/builtin/calltask/schema.go, engine/webhook/idem_memory.go
Adjusted 503 messages for SSE endpoints, schema descriptions and comments to use embedded terminology.
Scripting / tooling
scripts/markdown/check.go
Replaced go-retry logic with FSM-based orchestration for async flows (promptPreparationFSM, jobLifecycle, executorLifecycle) and propagated context usage.

Sequence Diagram(s)

sequenceDiagram
    participant CLI as CLI / TUI
    participant Form as Project Form
    participant Template as Template Generator
    participant Config as Config Resolver

    CLI->>Form: open init form (may pass default mode)
    Form->>Form: validate mode (memory/persistent/distributed)
    Form->>Form: toggle Docker prompt based on mode
    Form-->>CLI: return ProjectFormData{Mode}
    CLI->>Template: Generate project with Mode in GenerateOptions
    Template->>Config: build project config with Mode
    Config-->>Template: return mode-specific settings (DB, Redis, Temporal)
    Template->>Template: render mode-specific files (README, env, compozy.yaml)
    Template-->>CLI: emit generated files (Docker included only when distributed)
Loading
sequenceDiagram
    participant Server as Compozy Server
    participant Mode as Mode Resolver
    participant Cache as Cache Setup
    participant Temporal as Embedded Temporal

    Server->>Mode: resolve effective mode (component/global/default)
    alt Embedded (memory/persistent)
        Mode-->>Server: ModeMemory/ModePersistent
        Server->>Cache: setupEmbeddedCache(persistence?)
        Server->>Temporal: maybeStartEmbeddedTemporal(mode)
    else Distributed
        Mode-->>Server: ModeDistributed
        Server->>Cache: connectExternalRedis()
        Server->>Temporal: use external Temporal cluster
    end
    Cache-->>Server: ready
    Temporal-->>Server: ready
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Areas requiring extra attention:

  • pkg/config: validation, inheritance, env-prefix renames, and removal/deprecation of standalone semantics.
  • engine/infra (cache, server, temporal): embedded vs distributed initialization paths and resource lifecycle (embedded miniredis, persistence dir defaults).
  • test infrastructure: SetupDatabaseWithMode, provider-based repos, and broad test rewrites (SQLite in-memory vs Postgres containers) — ensure cleanup and cross-test isolation.
  • pkg/template: Mode propagation, template conditionals (Docker inclusion), and new Template/GenerateOptions surface.
  • scripts/markdown/check.go FSM refactor: verify state transitions, error handling, and integration with UI/lifecycle.
  • Database migrations and task repo changes: new execution_type values and qualified SQL columns for correctness across SQLite/Postgres.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.76% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The PR title "Add new modes" directly reflects the primary objective of the changeset, which is the introduction of new deployment modes (memory and persistent) to replace the legacy standalone mode system. The title accurately captures the main change across the codebase, including updates to configuration handling, CLI commands, infrastructure components, templates, and tests. While the title could be more detailed about the scope of refactoring (e.g., mentioning the replacement of standalone mode), it is clear and specific enough for a developer reviewing the repository history to understand that this PR concerns the deployment mode system. The title avoids vague terminology and meaningfully communicates the primary change.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch pn/modes

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (5)
cli/cmd/start/start.go (1)

89-91: Fix nil cobraCmd preventing --mode flag processing in JSON mode.

The function discards the received cobraCmd parameter and passes nil to handleStartTUI. This prevents resolveStartMode (line 56) from processing the --mode flag, as it returns early when cobraCmd == nil (line 101-103). Users invoking the start command in JSON mode won't be able to override the mode via the --mode flag.

Apply this diff to preserve the cobraCmd parameter:

-func handleStartJSON(ctx context.Context, _ *cobra.Command, executor *cmd.CommandExecutor, _ []string) error {
-	return handleStartTUI(ctx, nil, executor, nil)
+func handleStartJSON(ctx context.Context, cobraCmd *cobra.Command, executor *cmd.CommandExecutor, args []string) error {
+	return handleStartTUI(ctx, cobraCmd, executor, args)
 }
pkg/config/loader.go (1)

505-521: Update embedded Temporal error messaging

The errors still instruct users to set mode=standalone, but that mode was just removed. When someone runs in memory or persistent and forgets a required field, the message points them at an impossible fix. Please update these errors to reference the supported embedded modes (ModeMemory, ModePersistent) so the guidance matches the new behavior.

Apply this diff to adjust the messaging:

@@
-		return fmt.Errorf("temporal.standalone.bind_ip is required when mode=standalone")
+		return fmt.Errorf(
+			"temporal.standalone.bind_ip is required when temporal.mode is %q or %q",
+			ModeMemory,
+			ModePersistent,
+		)
@@
-		return fmt.Errorf("temporal.standalone.namespace is required when mode=standalone")
+		return fmt.Errorf(
+			"temporal.standalone.namespace is required when temporal.mode is %q or %q",
+			ModeMemory,
+			ModePersistent,
+		)
@@
-		return fmt.Errorf("temporal.standalone.cluster_name is required when mode=standalone")
+		return fmt.Errorf(
+			"temporal.standalone.cluster_name is required when temporal.mode is %q or %q",
+			ModeMemory,
+			ModePersistent,
+		)
test/integration/store/operations_test.go (1)

239-256: Fix the data race in the concurrent user creation test.

Each goroutine mutates userIDs[index] without synchronization. Even though the indices differ, they still touch the same underlying slice, so go test -race will flag this as a data race and the values are not guaranteed. Gather the results on a channel (or guard the write) and update userIDs from the main goroutine instead.

-		errChan := make(chan error, numUsers)
-		for i := 0; i < numUsers; i++ {
-			go func(index int) {
-				userID := core.MustNewID()
-				userIDs[index] = userID
-				user := &model.User{
-					ID:    userID,
-					Email: fmt.Sprintf("user%d@example.com", index),
-					Role:  model.RoleUser,
-				}
-				errChan <- authRepo.CreateUser(ctx, user)
-			}(i)
-		}
-
-		for i := 0; i < numUsers; i++ {
-			err := <-errChan
-			require.NoError(t, err, "concurrent user creation should succeed")
-		}
+		type creationResult struct {
+			index int
+			id    core.ID
+			err   error
+		}
+		results := make(chan creationResult, numUsers)
+		for i := 0; i < numUsers; i++ {
+			go func(index int) {
+				userID := core.MustNewID()
+				user := &model.User{
+					ID:    userID,
+					Email: fmt.Sprintf("user%d@example.com", index),
+					Role:  model.RoleUser,
+				}
+				results <- creationResult{
+					index: index,
+					id:    userID,
+					err:   authRepo.CreateUser(ctx, user),
+				}
+			}(i)
+		}
+
+		for i := 0; i < numUsers; i++ {
+			res := <-results
+			require.NoError(t, res.err, "concurrent user creation should succeed")
+			userIDs[res.index] = res.id
+		}
test/helpers/server/server.go (1)

131-141: Do not drop the config dependency from appstate.NewBaseDeps.

appstate.NewBaseDeps assumes a non-nil *config.Config and eagerly dereferences it to build repo factories, runtime knobs, and middleware state. Passing nil here regresses every harness boot with a nil-pointer panic inside appstate.NewState. Keep threading the loaded config through this helper.

Apply this diff:

-	state, store := buildApplicationState(t, proj, provider)
+	state, store := buildApplicationState(t, cfg, proj, provider)
@@
-func buildApplicationState(
-	t *testing.T,
-	proj *project.Config,
-	provider *repo.Provider,
-) (*appstate.State, resources.ResourceStore) {
-	deps := appstate.NewBaseDeps(proj, nil, provider, nil)
+func buildApplicationState(
+	t *testing.T,
+	cfg *config.Config,
+	proj *project.Config,
+	provider *repo.Provider,
+) (*appstate.State, resources.ResourceStore) {
+	deps := appstate.NewBaseDeps(proj, cfg, provider, nil)
scripts/markdown/check.go (1)

1184-1193: Batching now splits per issue instead of per file (regression)

createIssueBatches now chunks the flattened issue list by batchSize, so with the default --batch-size=1 every individual issue becomes its own job. Files with multiple unresolved issues now get split across multiple prompts, which defeats the “file group” batching described in the CLI help and was previously guaranteed by the per-file grouping logic. This is a blocking behavioral regression because the generated prompts no longer contain the full context for a file.

Please restore batching to operate on distinct codeFile groups (keeping all issues for a file together) before applying the batch-size cap. One way is to derive an ordered list of code files from p.collected, then accumulate whole groups until you reach the requested batch size:

 func (p *promptPreparationFSM) groupEntries() error {
-	p.batches = createIssueBatches(p.collected, p.cfg.batchSize)
-	if len(p.batches) == 0 {
-		return p.fail(fmt.Errorf("no batches created for prompt preparation"))
-	}
-	return p.transition(prepEventGrouped)
+	batches, err := createIssueBatchesByGroup(p.collected, p.cfg.groups, p.cfg.batchSize)
+	if err != nil {
+		return p.fail(err)
+	}
+	p.batches = batches
+	return p.transition(prepEventGrouped)
 }
@@
-func createIssueBatches(allIssues []issueEntry, batchSize int) [][]issueEntry {
-	batches := make([][]issueEntry, 0)
-	for i := 0; i < len(allIssues); i += batchSize {
-		end := i + batchSize
-		if end > len(allIssues) {
-			end = len(allIssues)
-		}
-		batches = append(batches, allIssues[i:end])
-	}
-	return batches
+func createIssueBatchesByGroup(
+	orderedIssues []issueEntry,
+	groups map[string][]issueEntry,
+	batchSize int,
+) ([][]issueEntry, error) {
+	if batchSize <= 0 {
+		batchSize = 1
+	}
+	orderedFiles := make([]string, 0, len(groups))
+	seen := make(map[string]struct{}, len(groups))
+	for _, issue := range orderedIssues {
+		if _, ok := seen[issue.codeFile]; ok {
+			continue
+		}
+		orderedFiles = append(orderedFiles, issue.codeFile)
+		seen[issue.codeFile] = struct{}{}
+	}
+	batches := make([][]issueEntry, 0, len(orderedFiles))
+	var (
+		current      []issueEntry
+		currentFiles int
+	)
+	for _, codeFile := range orderedFiles {
+		issues := groups[codeFile]
+		current = append(current, issues...)
+		currentFiles++
+		if currentFiles == batchSize {
+			batches = append(batches, current)
+			current = nil
+			currentFiles = 0
+		}
+	}
+	if len(current) > 0 {
+		batches = append(batches, current)
+	}
+	if len(batches) == 0 {
+		return nil, fmt.Errorf("no batches created for prompt preparation")
+	}
+	return batches, nil
 }

This keeps all issues for a file together and preserves the documented meaning of --batch-size.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 5679ced and bce1809.

⛔ Files ignored due to path filters (110)
  • cli/help/global-flags.md is excluded by !**/*.md
  • docs/content/docs/configuration/mode-configuration.mdx is excluded by !**/*.mdx
  • docs/content/docs/configuration/redis.mdx is excluded by !**/*.mdx
  • docs/content/docs/deployment/distributed-mode.mdx is excluded by !**/*.mdx
  • docs/content/docs/deployment/memory-mode.mdx is excluded by !**/*.mdx
  • docs/content/docs/deployment/meta.json is excluded by !**/*.json
  • docs/content/docs/deployment/persistent-mode.mdx is excluded by !**/*.mdx
  • docs/content/docs/deployment/standalone-mode.mdx is excluded by !**/*.mdx
  • docs/content/docs/examples/distributed-mode.mdx is excluded by !**/*.mdx
  • docs/content/docs/examples/index.mdx is excluded by !**/*.mdx
  • docs/content/docs/examples/memory-mode.mdx is excluded by !**/*.mdx
  • docs/content/docs/examples/meta.json is excluded by !**/*.json
  • docs/content/docs/examples/persistent-mode.mdx is excluded by !**/*.mdx
  • docs/content/docs/guides/meta.json is excluded by !**/*.json
  • docs/content/docs/guides/migrate-standalone-to-distributed.mdx is excluded by !**/*.mdx
  • docs/content/docs/guides/mode-migration-guide.mdx is excluded by !**/*.mdx
  • docs/content/docs/meta.json is excluded by !**/*.json
  • docs/content/docs/quick-start/index.mdx is excluded by !**/*.mdx
  • docs/swagger.json is excluded by !**/*.json, !docs/swagger.*
  • docs/swagger.yaml is excluded by !**/*.yaml, !docs/swagger.*
  • examples/README.md is excluded by !**/*.md
  • examples/configs/distributed-mode.yaml is excluded by !**/*.yaml
  • examples/configs/memory-mode.yaml is excluded by !**/*.yaml
  • examples/configs/persistent-mode.yaml is excluded by !**/*.yaml
  • examples/configs/workflows/echo.yaml is excluded by !**/*.yaml
  • examples/configs/workflows/summarize.yaml is excluded by !**/*.yaml
  • examples/configs/workflows/support-router.yaml is excluded by !**/*.yaml
  • examples/distributed-mode/README.md is excluded by !**/*.md
  • examples/distributed-mode/compozy.yaml is excluded by !**/*.yaml
  • examples/distributed-mode/docker-compose.yml is excluded by !**/*.yml
  • examples/distributed-mode/workflow.yaml is excluded by !**/*.yaml
  • examples/memory-mode/README.md is excluded by !**/*.md
  • examples/memory-mode/compozy.yaml is excluded by !**/*.yaml
  • examples/memory-mode/workflow.yaml is excluded by !**/*.yaml
  • examples/persistent-mode/README.md is excluded by !**/*.md
  • examples/persistent-mode/compozy.yaml is excluded by !**/*.yaml
  • examples/persistent-mode/workflow.yaml is excluded by !**/*.yaml
  • examples/standalone/README.md is excluded by !**/*.md
  • examples/standalone/compozy.yaml is excluded by !**/*.yaml
  • examples/standalone/workflow.yaml is excluded by !**/*.yaml
  • pkg/template/README.md is excluded by !**/*.md
  • schemas/agent.json is excluded by !**/*.json
  • schemas/cache.json is excluded by !**/*.json
  • schemas/compozy.json is excluded by !**/*.json
  • schemas/config-cli.json is excluded by !**/*.json
  • schemas/config-database.json is excluded by !**/*.json
  • schemas/config-knowledge.json is excluded by !**/*.json
  • schemas/config-llm.json is excluded by !**/*.json
  • schemas/config-mcpproxy.json is excluded by !**/*.json
  • schemas/config-redis.json is excluded by !**/*.json
  • schemas/config-server.json is excluded by !**/*.json
  • schemas/config-temporal.json is excluded by !**/*.json
  • schemas/config.json is excluded by !**/*.json
  • schemas/project.json is excluded by !**/*.json
  • schemas/provider.json is excluded by !**/*.json
  • schemas/runtime.json is excluded by !**/*.json
  • schemas/task.json is excluded by !**/*.json
  • schemas/vectordb.json is excluded by !**/*.json
  • tasks/prd-modes/_task_1.md is excluded by !**/*.md
  • tasks/prd-modes/_task_10.md is excluded by !**/*.md
  • tasks/prd-modes/_task_11.md is excluded by !**/*.md
  • tasks/prd-modes/_task_12.md is excluded by !**/*.md
  • tasks/prd-modes/_task_13.md is excluded by !**/*.md
  • tasks/prd-modes/_task_14.md is excluded by !**/*.md
  • tasks/prd-modes/_task_15.md is excluded by !**/*.md
  • tasks/prd-modes/_task_16.md is excluded by !**/*.md
  • tasks/prd-modes/_task_17.md is excluded by !**/*.md
  • tasks/prd-modes/_task_18.md is excluded by !**/*.md
  • tasks/prd-modes/_task_19.md is excluded by !**/*.md
  • tasks/prd-modes/_task_2.md is excluded by !**/*.md
  • tasks/prd-modes/_task_20.md is excluded by !**/*.md
  • tasks/prd-modes/_task_21.md is excluded by !**/*.md
  • tasks/prd-modes/_task_22.md is excluded by !**/*.md
  • tasks/prd-modes/_task_23.0.md is excluded by !**/*.md
  • tasks/prd-modes/_task_24.0.md is excluded by !**/*.md
  • tasks/prd-modes/_task_25.0.md is excluded by !**/*.md
  • tasks/prd-modes/_task_26.0.md is excluded by !**/*.md
  • tasks/prd-modes/_task_27.md is excluded by !**/*.md
  • tasks/prd-modes/_task_28.md is excluded by !**/*.md
  • tasks/prd-modes/_task_29.md is excluded by !**/*.md
  • tasks/prd-modes/_task_3.md is excluded by !**/*.md
  • tasks/prd-modes/_task_4.md is excluded by !**/*.md
  • tasks/prd-modes/_task_5.md is excluded by !**/*.md
  • tasks/prd-modes/_task_6.md is excluded by !**/*.md
  • tasks/prd-modes/_task_7.md is excluded by !**/*.md
  • tasks/prd-modes/_task_8.0.md is excluded by !**/*.md
  • tasks/prd-modes/_task_8.md is excluded by !**/*.md
  • tasks/prd-modes/_task_9.md is excluded by !**/*.md
  • tasks/prd-modes/_tasks.md is excluded by !**/*.md
  • tasks/prd-modes/_techspec.md is excluded by !**/*.md
  • tasks/prd-redis/_docs.md is excluded by !**/*.md
  • tasks/prd-redis/_examples.md is excluded by !**/*.md
  • tasks/prd-redis/_prd.md is excluded by !**/*.md
  • tasks/prd-redis/_task_01.md is excluded by !**/*.md
  • tasks/prd-redis/_task_02.md is excluded by !**/*.md
  • tasks/prd-redis/_task_03.md is excluded by !**/*.md
  • tasks/prd-redis/_task_04.md is excluded by !**/*.md
  • tasks/prd-redis/_task_05.md is excluded by !**/*.md
  • tasks/prd-redis/_task_06.md is excluded by !**/*.md
  • tasks/prd-redis/_task_07.md is excluded by !**/*.md
  • tasks/prd-redis/_task_08.md is excluded by !**/*.md
  • tasks/prd-redis/_task_09.md is excluded by !**/*.md
  • tasks/prd-redis/_task_10.md is excluded by !**/*.md
  • tasks/prd-redis/_task_11.md is excluded by !**/*.md
  • tasks/prd-redis/_task_12.md is excluded by !**/*.md
  • tasks/prd-redis/_task_13.md is excluded by !**/*.md
  • tasks/prd-redis/_tasks.md is excluded by !**/*.md
  • tasks/prd-redis/_techspec.md is excluded by !**/*.md
  • tasks/prd-redis/_tests.md is excluded by !**/*.md
  • test/integration/README.md is excluded by !**/*.md
📒 Files selected for processing (63)
  • cli/cmd/config/config_test.go (5 hunks)
  • cli/cmd/init/components/project_form.go (5 hunks)
  • cli/cmd/init/init.go (12 hunks)
  • cli/cmd/start/start.go (2 hunks)
  • cli/cmd/start/start_test.go (2 hunks)
  • cli/helpers/flag_categories.go (1 hunks)
  • docs/docs.go (12 hunks)
  • engine/infra/cache/miniredis_standalone.go (1 hunks)
  • engine/infra/cache/mod.go (3 hunks)
  • engine/infra/cache/mod_test.go (2 hunks)
  • engine/infra/postgres/migrations.go (3 hunks)
  • engine/infra/postgres/taskrepo.go (1 hunks)
  • engine/infra/server/dependencies.go (5 hunks)
  • engine/infra/server/dependencies_test.go (1 hunks)
  • engine/infra/server/mcp.go (3 hunks)
  • engine/infra/server/mcp_test.go (2 hunks)
  • engine/infra/server/server.go (2 hunks)
  • engine/infra/sqlite/migrations.go (2 hunks)
  • engine/infra/sqlite/migrations/20250603124915_create_task_states.sql (1 hunks)
  • engine/infra/sqlite/taskrepo.go (3 hunks)
  • engine/worker/embedded/namespace.go (1 hunks)
  • examples/distributed-mode/.env.example (1 hunks)
  • examples/memory-mode/.env.example (1 hunks)
  • examples/memory-mode/api.http (1 hunks)
  • examples/memory-mode/edge-deployment/Dockerfile.edge (1 hunks)
  • examples/persistent-mode/.env.example (1 hunks)
  • examples/standalone/.env.example (0 hunks)
  • pkg/config/config.go (9 hunks)
  • pkg/config/config_test.go (12 hunks)
  • pkg/config/definition/schema.go (6 hunks)
  • pkg/config/loader.go (7 hunks)
  • pkg/config/loader_test.go (4 hunks)
  • pkg/config/resolver.go (4 hunks)
  • pkg/config/resolver_test.go (1 hunks)
  • pkg/template/generator.go (3 hunks)
  • pkg/template/service.go (2 hunks)
  • pkg/template/templates/basic/README.md.tmpl (1 hunks)
  • pkg/template/templates/basic/basic.go (4 hunks)
  • pkg/template/templates/basic/basic_test.go (1 hunks)
  • pkg/template/templates/basic/compozy.yaml.tmpl (1 hunks)
  • pkg/template/templates/basic/env.example.tmpl (1 hunks)
  • pkg/template/templates/basic/gitignore.tmpl (1 hunks)
  • pkg/template/types.go (2 hunks)
  • pkg/template/types_test.go (1 hunks)
  • scripts/markdown/check.go (29 hunks)
  • test/helpers/database.go (4 hunks)
  • test/helpers/database_test.go (2 hunks)
  • test/helpers/repo.go (1 hunks)
  • test/helpers/server/server.go (4 hunks)
  • test/integration/cache/adapter_contract_test.go (1 hunks)
  • test/integration/database/multi_driver_test.go (2 hunks)
  • test/integration/database/sqlite_specific_test.go (1 hunks)
  • test/integration/repo/repo_test_helpers.go (1 hunks)
  • test/integration/repo/task_test.go (0 hunks)
  • test/integration/repo/workflow_test.go (0 hunks)
  • test/integration/server/executions_integration_test.go (2 hunks)
  • test/integration/server/mcp_health_test.go (1 hunks)
  • test/integration/standalone/helpers.go (4 hunks)
  • test/integration/standalone/workflow_test.go (2 hunks)
  • test/integration/store/operations_test.go (6 hunks)
  • test/integration/tasks/basic/response_handler_test.go (2 hunks)
  • test/integration/tasks/core/concurrent_test.go (1 hunks)
  • test/integration/tasks/helpers/setup.go (2 hunks)
💤 Files with no reviewable changes (3)
  • examples/standalone/.env.example
  • test/integration/repo/workflow_test.go
  • test/integration/repo/task_test.go
🧰 Additional context used
📓 Path-based instructions (20)
**/*.go

📄 CodeRabbit inference engine (.cursor/rules/api-standards.mdc)

**/*.go: Return properly structured error responses
Use middleware for cross-cutting concerns (e.g., logging, auth, rate limiting)
Implement proper authentication and authorization in the API
Apply rate limiting and request validation
Version API routes under the prefix /api/v0/
Use gin-gonic/gin for HTTP APIs
Ensure consistent response formats across all endpoints
Use appropriate HTTP status codes (200, 201, 400, 401, 403, 404, 500)
Return JSON responses with a consistent error structure
Update Swagger annotations for all API changes
Generate Swagger docs served at /swagger/index.html using swaggo/swag
Include request and response examples in Swagger annotations
Document all parameters, headers, and error responses in Swagger
Success response body should contain fields: data and message ("Success")
Error response body should contain fields: error and details

**/*.go: Retrieve the logger via logger.FromContext(ctx) inside runtime code (handlers, services, workers)
Retrieve configuration via config.FromContext(ctx) inside runtime code (handlers, services, workers)
Attach *config.Manager at process edges using config.ContextWithManager(ctx, mgr)
Build the logger with logger.SetupLogger(...) at startup and attach with logger.ContextWithLogger(ctx, log)
For HTTP servers, ensure request contexts inherit BOTH manager and logger via middleware
Do not pass loggers via function parameters or dependency injection; always use context-backed retrieval
Do not use a global configuration singleton; read config from context
CLI/root flow: parse flags → construct sources → mgr.Load(...) → attach manager to ctx → setup logger honoring cfg.CLI.Debug/Quiet → attach logger to ctx → propagate ctx
Server startup should use the CLI-provided ctx and add middleware that sets c.Request = c.Request.WithContext(logger.ContextWithLogger(config.ContextWithManager(c.Request.Context(), mgr), log))
Optionally set http.Server.BaseContext to a parent context carrying manager and logger so all req...

Files:

  • engine/infra/postgres/taskrepo.go
  • pkg/template/service.go
  • engine/infra/cache/miniredis_standalone.go
  • test/integration/database/multi_driver_test.go
  • engine/worker/embedded/namespace.go
  • engine/infra/sqlite/migrations.go
  • cli/cmd/start/start_test.go
  • engine/infra/postgres/migrations.go
  • pkg/config/resolver.go
  • engine/infra/server/mcp_test.go
  • cli/helpers/flag_categories.go
  • engine/infra/sqlite/taskrepo.go
  • pkg/config/loader_test.go
  • pkg/template/templates/basic/basic_test.go
  • engine/infra/server/dependencies_test.go
  • docs/docs.go
  • test/integration/standalone/workflow_test.go
  • cli/cmd/config/config_test.go
  • engine/infra/server/dependencies.go
  • pkg/template/types_test.go
  • test/integration/store/operations_test.go
  • pkg/template/generator.go
  • pkg/config/config.go
  • pkg/config/resolver_test.go
  • test/integration/repo/repo_test_helpers.go
  • test/integration/cache/adapter_contract_test.go
  • engine/infra/cache/mod.go
  • test/integration/server/mcp_health_test.go
  • scripts/markdown/check.go
  • test/integration/standalone/helpers.go
  • engine/infra/cache/mod_test.go
  • test/integration/server/executions_integration_test.go
  • test/helpers/database_test.go
  • engine/infra/server/mcp.go
  • test/integration/tasks/basic/response_handler_test.go
  • pkg/template/types.go
  • engine/infra/server/server.go
  • test/helpers/repo.go
  • pkg/config/loader.go
  • pkg/template/templates/basic/basic.go
  • cli/cmd/init/components/project_form.go
  • test/integration/tasks/core/concurrent_test.go
  • cli/cmd/start/start.go
  • test/helpers/database.go
  • cli/cmd/init/init.go
  • test/helpers/server/server.go
  • pkg/config/config_test.go
  • test/integration/tasks/helpers/setup.go
  • test/integration/database/sqlite_specific_test.go
  • pkg/config/definition/schema.go
**/!(*_test).go

📄 CodeRabbit inference engine (.cursor/rules/magic-numbers.mdc)

**/!(*_test).go: NEVER introduce magic numbers in runtime Go code; replace unexplained numeric literals with named constants or configuration
Operator-tunable values MUST be sourced from configuration as defined in @.cursor/rules/global-config.mdc
Fetch configuration via config.FromContext(ctx); do not use global singletons
Promote tunable values (timeouts, deadlines, polling intervals, retry/backoff counts and factors, concurrency limits, queue sizes, buffer/payload limits, behavior thresholds) to configuration

In runtime code, properly inherit context; never use context.Background() in code paths

In runtime code paths, inherit context properly; never use context.Background()

In runtime code paths, never use context.Background(); properly inherit context

In runtime code, properly inherit context; never use context.Background()

Files:

  • engine/infra/postgres/taskrepo.go
  • pkg/template/service.go
  • engine/infra/cache/miniredis_standalone.go
  • engine/worker/embedded/namespace.go
  • engine/infra/sqlite/migrations.go
  • engine/infra/postgres/migrations.go
  • pkg/config/resolver.go
  • cli/helpers/flag_categories.go
  • engine/infra/sqlite/taskrepo.go
  • docs/docs.go
  • engine/infra/server/dependencies.go
  • pkg/template/generator.go
  • pkg/config/config.go
  • test/integration/repo/repo_test_helpers.go
  • engine/infra/cache/mod.go
  • scripts/markdown/check.go
  • test/integration/standalone/helpers.go
  • engine/infra/server/mcp.go
  • pkg/template/types.go
  • engine/infra/server/server.go
  • test/helpers/repo.go
  • pkg/config/loader.go
  • pkg/template/templates/basic/basic.go
  • cli/cmd/init/components/project_form.go
  • cli/cmd/start/start.go
  • test/helpers/database.go
  • cli/cmd/init/init.go
  • test/helpers/server/server.go
  • test/integration/tasks/helpers/setup.go
  • pkg/config/definition/schema.go
engine/infra/**/*.go

📄 CodeRabbit inference engine (.cursor/rules/architecture.mdc)

engine/infra/**/*.go: Infrastructure Layer (engine/infra): implement adapters for DB, cache, HTTP, storage, monitoring; must implement Application Layer interfaces
Adapter implementations belong in Infrastructure Layer and must implement Application Layer interfaces (no business logic leakage)
Infrastructure depends inward: Infrastructure → Application → Domain; avoid imports from cli and cross-infra coupling

Files:

  • engine/infra/postgres/taskrepo.go
  • engine/infra/cache/miniredis_standalone.go
  • engine/infra/sqlite/migrations.go
  • engine/infra/postgres/migrations.go
  • engine/infra/server/mcp_test.go
  • engine/infra/sqlite/taskrepo.go
  • engine/infra/server/dependencies_test.go
  • engine/infra/server/dependencies.go
  • engine/infra/cache/mod.go
  • engine/infra/cache/mod_test.go
  • engine/infra/server/mcp.go
  • engine/infra/server/server.go
{engine,pkg,cli}/**/*.go

📄 CodeRabbit inference engine (.cursor/rules/architecture.mdc)

Context as the first parameter for I/O or long-running operations; always propagate and handle cancellation

Files:

  • engine/infra/postgres/taskrepo.go
  • pkg/template/service.go
  • engine/infra/cache/miniredis_standalone.go
  • engine/worker/embedded/namespace.go
  • engine/infra/sqlite/migrations.go
  • cli/cmd/start/start_test.go
  • engine/infra/postgres/migrations.go
  • pkg/config/resolver.go
  • engine/infra/server/mcp_test.go
  • cli/helpers/flag_categories.go
  • engine/infra/sqlite/taskrepo.go
  • pkg/config/loader_test.go
  • pkg/template/templates/basic/basic_test.go
  • engine/infra/server/dependencies_test.go
  • cli/cmd/config/config_test.go
  • engine/infra/server/dependencies.go
  • pkg/template/types_test.go
  • pkg/template/generator.go
  • pkg/config/config.go
  • pkg/config/resolver_test.go
  • engine/infra/cache/mod.go
  • engine/infra/cache/mod_test.go
  • engine/infra/server/mcp.go
  • pkg/template/types.go
  • engine/infra/server/server.go
  • pkg/config/loader.go
  • pkg/template/templates/basic/basic.go
  • cli/cmd/init/components/project_form.go
  • cli/cmd/start/start.go
  • cli/cmd/init/init.go
  • pkg/config/config_test.go
  • pkg/config/definition/schema.go
pkg/**/*.go

📄 CodeRabbit inference engine (.cursor/rules/architecture.mdc)

Shared Packages (pkg): provide framework-level utilities (config, logging, templates, schema generation); must not contain business logic

Files:

  • pkg/template/service.go
  • pkg/config/resolver.go
  • pkg/config/loader_test.go
  • pkg/template/templates/basic/basic_test.go
  • pkg/template/types_test.go
  • pkg/template/generator.go
  • pkg/config/config.go
  • pkg/config/resolver_test.go
  • pkg/template/types.go
  • pkg/config/loader.go
  • pkg/template/templates/basic/basic.go
  • pkg/config/config_test.go
  • pkg/config/definition/schema.go
**/*_test.go

📄 CodeRabbit inference engine (.cursor/rules/logger-config.mdc)

**/*_test.go: In tests, set up configuration with config.Initialize or config.NewManager(...).Load(...) and attach via config.ContextWithManager
In tests, prefer logger.NewForTests() and attach with logger.ContextWithLogger
In tests, mock or stub external tools/services; do not introduce DI of logger/config into code under test

**/*_test.go: Prefer local test constants (e.g., const testTimeout = 5 * time.Second) in tests
Inline trivial literals in tests when intent is clear
Do not duplicate production constants in tests; import them or assert relative behavior

**/*_test.go: All tests pass and follow the established testing patterns
Code is well-tested with both unit and integration tests
Tests should follow the t.Run("Should...") subtest naming pattern
Ensure adequate test coverage

**/*_test.go: All Go tests must use t.Run("Should describe behavior", ...) subtests for each behavior
Use stretchr/testify for assertions and mocks in tests
Do not use testify suite patterns (no suite.Suite embedding or suite-based structures)
Do not use suite methods like s.Equal(), s.NoError(), or s.T()
Avoid weak assertions like assert.Error(t, err); use specific error validation instead
Prefer specific error assertions like assert.ErrorContains and assert.ErrorAs for validating errors
Unit tests should be placed alongside implementation files as *_test.go
Use testify/mock for mocking external dependencies or complex interfaces

In tests, never use context.Background(); use t.Context() instead

Aim for 80%+ test coverage on business logic; write focused, isolated tests

**/*_test.go: Use stretchr/testify for assertions and mocks; import as github.com/stretchr/testify/assert and github.com/stretchr/testify/mock; replace custom mocks with testify/mock
Use project test helpers (utils.SetupTest, utils.SetupFixture, etc.) in tests

In tests, never use context.Background(); use t.Context()

Files:

  • test/integration/database/multi_driver_test.go
  • cli/cmd/start/start_test.go
  • engine/infra/server/mcp_test.go
  • pkg/config/loader_test.go
  • pkg/template/templates/basic/basic_test.go
  • engine/infra/server/dependencies_test.go
  • test/integration/standalone/workflow_test.go
  • cli/cmd/config/config_test.go
  • pkg/template/types_test.go
  • test/integration/store/operations_test.go
  • pkg/config/resolver_test.go
  • test/integration/cache/adapter_contract_test.go
  • test/integration/server/mcp_health_test.go
  • engine/infra/cache/mod_test.go
  • test/integration/server/executions_integration_test.go
  • test/helpers/database_test.go
  • test/integration/tasks/basic/response_handler_test.go
  • test/integration/tasks/core/concurrent_test.go
  • pkg/config/config_test.go
  • test/integration/database/sqlite_specific_test.go
test/integration/**/*_test.go

📄 CodeRabbit inference engine (.cursor/rules/test-standards.mdc)

Integration tests must reside under test/integration/

Files:

  • test/integration/database/multi_driver_test.go
  • test/integration/standalone/workflow_test.go
  • test/integration/store/operations_test.go
  • test/integration/cache/adapter_contract_test.go
  • test/integration/server/mcp_health_test.go
  • test/integration/server/executions_integration_test.go
  • test/integration/tasks/basic/response_handler_test.go
  • test/integration/tasks/core/concurrent_test.go
  • test/integration/database/sqlite_specific_test.go
test/integration/**/*.go

📄 CodeRabbit inference engine (.cursor/rules/architecture.mdc)

Place integration tests under test/integration; keep them exercising cross-component behavior

Files:

  • test/integration/database/multi_driver_test.go
  • test/integration/standalone/workflow_test.go
  • test/integration/store/operations_test.go
  • test/integration/repo/repo_test_helpers.go
  • test/integration/cache/adapter_contract_test.go
  • test/integration/server/mcp_health_test.go
  • test/integration/standalone/helpers.go
  • test/integration/server/executions_integration_test.go
  • test/integration/tasks/basic/response_handler_test.go
  • test/integration/tasks/core/concurrent_test.go
  • test/integration/tasks/helpers/setup.go
  • test/integration/database/sqlite_specific_test.go
engine/{agent,task,task2,tool,workflow,runtime,llm,memory,memorycfg,knowledge,model,mcp,webhook,attachment,resources,auth,autoload,project,schema,worker}/**/*.go

📄 CodeRabbit inference engine (.cursor/rules/architecture.mdc)

engine/{agent,task,task2,tool,workflow,runtime,llm,memory,memorycfg,knowledge,model,mcp,webhook,attachment,resources,auth,autoload,project,schema,worker}/**/*.go: Application Layer (engine/): implement domain-specific business logic and ports; organize by domain with uc/ and router/ subpackages
Port interfaces (e.g., repositories, external services) are defined in Application Layer packages where they are used
Application layer depends inward: Application → Domain; avoid depending on infrastructure

Files:

  • engine/worker/embedded/namespace.go
cli/**/*.go

📄 CodeRabbit inference engine (.cursor/rules/architecture.mdc)

cli/**/*.go: Presentation Layer (cli): implement CLI, user interaction/formatting, and API client; no business logic
CLI depends inward: CLI → Application → Domain; do not depend directly on infrastructure

Files:

  • cli/cmd/start/start_test.go
  • cli/helpers/flag_categories.go
  • cli/cmd/config/config_test.go
  • cli/cmd/init/components/project_form.go
  • cli/cmd/start/start.go
  • cli/cmd/init/init.go
pkg/config/**/*.go

📄 CodeRabbit inference engine (.cursor/rules/architecture.mdc)

Global configuration resides in pkg/config; expose retrieval via context (config.FromContext) and provide defaults; avoid global singletons

Files:

  • pkg/config/resolver.go
  • pkg/config/loader_test.go
  • pkg/config/config.go
  • pkg/config/resolver_test.go
  • pkg/config/loader.go
  • pkg/config/config_test.go
  • pkg/config/definition/schema.go
cli/helpers/flag_categories.go

📄 CodeRabbit inference engine (.cursor/rules/global-config.mdc)

cli/helpers/flag_categories.go: Categorize new CLI flags by adding their names to the appropriate category in flag_categories.go for better help UX
For new categories, add a category block or include flags in an existing category in flag_categories.go

Environment variable overrides follow ATTACHMENTS_* naming (e.g., ATTACHMENTS_DOWNLOAD_TIMEOUT); ensure mapping from flags to env vars uses this prefix

Files:

  • cli/helpers/flag_categories.go
pkg/config/**/*_test.go

📄 CodeRabbit inference engine (.cursor/rules/global-config.mdc)

Add or extend tests under pkg/config/*_test.go when introducing validation or complex defaults

Files:

  • pkg/config/loader_test.go
  • pkg/config/resolver_test.go
  • pkg/config/config_test.go
docs/**/*.go

📄 CodeRabbit inference engine (docs/.cursor/rules/review-checklist.mdc)

docs/**/*.go: Code must be formatted with go fmt
All linter warnings must be addressed
Error handling must follow project patterns
Security considerations must be addressed (e.g., no exposed secrets or unvalidated inputs)
Errors must be handled appropriately and with context
Interfaces must be used appropriately to define behavior
Code must pass all linter checks
Code must be secure and performant
Dependencies must be injected properly
Context must be propagated correctly
Hardcoded values that should be configurable must be avoided
Missing context propagation in functions that make external calls must be addressed
Performance issues like unnecessary allocations or inefficient algorithms must be avoided

docs/**/*.go: Use section comments with dashes for visual separation in Go code, formatted as:
// -----------------------------------------------------------------------------
// Section Name
// -----------------------------------------------------------------------------

Files:

  • docs/docs.go
pkg/config/config.go

📄 CodeRabbit inference engine (.cursor/rules/global-config.mdc)

pkg/config/config.go: Add the new field to the typed config struct with tags: koanf/json/yaml/mapstructure; include env tag when applicable; add validate tag if needed; use SensitiveString or sensitive:"true" for secrets
Map from registry to typed struct in build

Config using getString/getInt/getBool/getDuration/getInt64/getStringSlice
For secrets, prefer SensitiveString type or sensitive:"true" tag to enable automatic JSON redaction
When creating a new category, define type
Config struct with full tagging and validation
Add the new section to the root Config with koanf/json/yaml/mapstructure tags
Implement build
Config(registry *definition.Registry) to map defaults from the registry to the typed struct
Always include koanf, json, yaml, and mapstructure tags on config struct fields; include env when applicable

Files:

  • pkg/config/config.go
{pkg/config/config.go,pkg/config/definition/schema.go}

📄 CodeRabbit inference engine (.cursor/rules/global-config.mdc)

Environment variable names must be UPPER_SNAKE_CASE with domain prefixes (e.g., SERVER_, DB_, RUNTIME_, CLI uses COMPOZY_)

Files:

  • pkg/config/config.go
  • pkg/config/definition/schema.go
{compozy.yaml,examples/**/compozy.yaml,pkg/template/templates/**/compozy.yaml.tmpl}

📄 CodeRabbit inference engine (.cursor/rules/compozy/llm-providers.mdc)

{compozy.yaml,examples/**/compozy.yaml,pkg/template/templates/**/compozy.yaml.tmpl}: Define LLM providers under models in Compozy configuration files, not elsewhere
Each models entry must include required fields: provider and model (schemas/provider.json#ProviderConfig)
Use environment or secrets templates for api_key (e.g., "{{ .env.OPENAI_API_KEY }}"); do not hardcode API keys
Provider name must be one of: openai, anthropic, google, groq, ollama, deepseek, xai, mock
For provider: anthropic, do not set organization (unsupported)
For provider: google, do not set api_url or organization (not supported)
For provider: ollama (local), include api_url (e.g., http://localhost:11434); api_key is not required
Consider setting cost-control params under params (e.g., max_tokens, temperature) for expensive models
Use provider-appropriate features only (e.g., structured outputs and organization for OpenAI; avoid unsupported combinations)

Files:

  • pkg/template/templates/basic/compozy.yaml.tmpl
test/helpers/**

📄 CodeRabbit inference engine (.cursor/rules/test-standards.mdc)

Use test/helpers/ for shared test utilities and reusable helpers

Files:

  • test/helpers/database_test.go
  • test/helpers/repo.go
  • test/helpers/database.go
  • test/helpers/server/server.go
pkg/config/loader.go

📄 CodeRabbit inference engine (.cursor/rules/global-config.mdc)

pkg/config/loader.go: Implement cross-field validation in validateCustom when struct tag validation is insufficient
Extend validateCustom for cross-field constraints in new categories when struct tags are insufficient

Files:

  • pkg/config/loader.go
pkg/config/definition/schema.go

📄 CodeRabbit inference engine (.cursor/rules/global-config.mdc)

pkg/config/definition/schema.go: Use pkg/config/definition/schema.go as the single source of truth for configuration by registering fields in the registry
Add new property by registering it with registry.Register(&FieldDef{Path, Default, CLIFlag, EnvVar, Type, Help}); keep path naming category.property_name (snake_case)
Register all fields of a new category in register

Fields and include it in CreateRegistry()
Config path format must be section.snake_case_property when registering fields
CLI flags in registry must use kebab-case (CLIFlag)
Durations should use time.Duration and defaults in the registry must be time.Duration values

Files:

  • pkg/config/definition/schema.go
🧬 Code graph analysis (41)
engine/infra/postgres/taskrepo.go (1)
engine/task/domain.go (2)
  • ExecutionType (18-18)
  • ExecutionBasic (21-21)
pkg/template/service.go (2)
cli/tui/models/base.go (1)
  • Mode (10-10)
pkg/template/types.go (2)
  • DefaultMode (12-12)
  • ValidateMode (70-82)
test/integration/database/multi_driver_test.go (1)
test/helpers/database.go (2)
  • SetupPostgresContainer (426-429)
  • SetupTestDatabase (406-421)
cli/cmd/start/start_test.go (1)
pkg/config/config.go (1)
  • SourceDefault (2013-2013)
pkg/config/resolver.go (1)
pkg/config/config.go (1)
  • Config (58-148)
engine/infra/server/mcp_test.go (1)
pkg/config/resolver.go (2)
  • ModeMemory (7-7)
  • ModeDistributed (9-9)
engine/infra/sqlite/taskrepo.go (1)
engine/task/domain.go (2)
  • ExecutionType (18-18)
  • ExecutionBasic (21-21)
pkg/config/loader_test.go (3)
pkg/config/resolver.go (3)
  • ModeMemory (7-7)
  • ModePersistent (8-8)
  • ModeDistributed (9-9)
pkg/config/loader.go (1)
  • NewService (54-67)
pkg/config/config.go (1)
  • Default (2023-2025)
pkg/template/templates/basic/basic_test.go (4)
pkg/template/templates/basic/basic.go (1)
  • Template (39-39)
pkg/template/types.go (1)
  • GenerateOptions (57-67)
pkg/template/service.go (1)
  • GetService (23-31)
pkg/logger/mod.go (2)
  • ContextWithLogger (39-41)
  • NewForTests (199-201)
test/integration/standalone/workflow_test.go (1)
test/integration/standalone/helpers.go (1)
  • SetupMemoryTestEnv (57-95)
cli/cmd/config/config_test.go (2)
pkg/logger/mod.go (2)
  • ContextWithLogger (39-41)
  • NewForTests (199-201)
pkg/config/resolver.go (3)
  • ModeMemory (7-7)
  • ModeDistributed (9-9)
  • ModePersistent (8-8)
engine/infra/server/dependencies.go (3)
pkg/config/resolver.go (2)
  • ModeMemory (7-7)
  • ModePersistent (8-8)
pkg/config/config.go (1)
  • Config (58-148)
engine/worker/embedded/config.go (1)
  • Config (34-67)
pkg/template/types_test.go (1)
pkg/template/types.go (1)
  • ValidateMode (70-82)
test/integration/store/operations_test.go (3)
test/helpers/database.go (1)
  • SetupTestDatabase (406-421)
engine/infra/postgres/taskrepo.go (1)
  • NewTaskRepo (91-93)
engine/infra/sqlite/taskrepo.go (1)
  • NewTaskRepo (70-72)
pkg/template/generator.go (1)
cli/tui/models/base.go (1)
  • Mode (10-10)
pkg/config/config.go (1)
pkg/config/resolver.go (2)
  • ModeMemory (7-7)
  • ModePersistent (8-8)
pkg/config/resolver_test.go (2)
pkg/config/resolver.go (5)
  • ModeDistributed (9-9)
  • ModeMemory (7-7)
  • ModePersistent (8-8)
  • ModeRemoteTemporal (11-11)
  • ResolveMode (20-28)
pkg/config/config.go (5)
  • Config (58-148)
  • RedisConfig (1322-1434)
  • TemporalConfig (550-586)
  • MCPProxyConfig (1711-1759)
  • DatabaseConfig (310-425)
test/integration/repo/repo_test_helpers.go (1)
test/helpers/repo.go (1)
  • SetupTestRepos (14-28)
test/integration/cache/adapter_contract_test.go (1)
pkg/config/resolver.go (1)
  • ModePersistent (8-8)
engine/infra/cache/mod.go (2)
pkg/config/resolver.go (3)
  • ModeMemory (7-7)
  • ModePersistent (8-8)
  • ModeDistributed (9-9)
pkg/config/config.go (2)
  • RedisConfig (1322-1434)
  • Config (58-148)
test/integration/standalone/helpers.go (2)
cli/tui/models/base.go (1)
  • Mode (10-10)
pkg/config/resolver.go (1)
  • ModeMemory (7-7)
engine/infra/cache/mod_test.go (5)
pkg/logger/mod.go (2)
  • ContextWithLogger (39-41)
  • NewForTests (199-201)
pkg/config/provider.go (2)
  • NewDefaultProvider (233-237)
  • NewEnvProvider (21-23)
pkg/config/context.go (1)
  • ContextWithManager (19-21)
pkg/config/resolver.go (3)
  • ModeMemory (7-7)
  • ModePersistent (8-8)
  • ModeDistributed (9-9)
engine/infra/cache/mod.go (1)
  • SetupCache (53-87)
test/integration/server/executions_integration_test.go (1)
test/helpers/database.go (1)
  • SetupTestDatabase (406-421)
test/helpers/database_test.go (2)
test/helpers/database.go (1)
  • SetupDatabaseWithMode (282-318)
pkg/config/resolver.go (3)
  • ModeMemory (7-7)
  • ModePersistent (8-8)
  • ModeDistributed (9-9)
engine/infra/server/mcp.go (1)
pkg/config/resolver.go (2)
  • ModeMemory (7-7)
  • ModePersistent (8-8)
test/integration/tasks/basic/response_handler_test.go (1)
test/integration/tasks/helpers/setup.go (1)
  • NewTestSetupWithDriver (39-70)
pkg/template/types.go (1)
cli/tui/models/base.go (1)
  • Mode (10-10)
engine/infra/server/server.go (1)
pkg/config/resolver.go (1)
  • ModeMemory (7-7)
test/helpers/repo.go (3)
test/helpers/database.go (1)
  • SetupTestDatabase (406-421)
engine/infra/postgres/taskrepo.go (1)
  • NewTaskRepo (91-93)
engine/infra/sqlite/taskrepo.go (1)
  • NewTaskRepo (70-72)
pkg/config/loader.go (3)
pkg/config/config.go (1)
  • Config (58-148)
engine/worker/embedded/config.go (1)
  • Config (34-67)
pkg/config/resolver.go (4)
  • ModeMemory (7-7)
  • ModePersistent (8-8)
  • ModeDistributed (9-9)
  • ModeRemoteTemporal (11-11)
pkg/template/templates/basic/basic.go (1)
cli/tui/models/base.go (1)
  • Mode (10-10)
cli/cmd/init/components/project_form.go (2)
cli/tui/models/base.go (1)
  • Mode (10-10)
cli/cmd/init/init.go (1)
  • Options (30-42)
test/integration/tasks/core/concurrent_test.go (1)
test/integration/tasks/helpers/setup.go (1)
  • NewTestSetupWithDriver (39-70)
cli/cmd/start/start.go (2)
cli/tui/models/base.go (1)
  • Mode (10-10)
pkg/config/resolver.go (3)
  • ModeMemory (7-7)
  • ModePersistent (8-8)
  • ModeDistributed (9-9)
test/helpers/database.go (6)
pkg/config/resolver.go (3)
  • ModeMemory (7-7)
  • ModePersistent (8-8)
  • ModeDistributed (9-9)
pkg/config/config.go (1)
  • Config (58-148)
engine/infra/postgres/migrations.go (1)
  • ApplyMigrations (25-32)
engine/infra/sqlite/migrations.go (1)
  • ApplyMigrations (21-55)
test/helpers/testcontainer_retry.go (1)
  • SetupTestReposWithRetry (31-66)
engine/infra/repo/provider.go (1)
  • Provider (24-29)
cli/cmd/init/init.go (3)
cli/tui/models/base.go (1)
  • Mode (10-10)
pkg/template/service.go (1)
  • GetService (23-31)
pkg/template/types.go (1)
  • GenerateOptions (57-67)
test/helpers/server/server.go (1)
test/helpers/database.go (1)
  • SetupTestDatabase (406-421)
pkg/config/config_test.go (5)
pkg/config/resolver.go (5)
  • ModeMemory (7-7)
  • ResolveMode (20-28)
  • ModePersistent (8-8)
  • ModeDistributed (9-9)
  • ModeRemoteTemporal (11-11)
pkg/config/config.go (1)
  • Default (2023-2025)
pkg/config/loader.go (1)
  • NewService (54-67)
pkg/config/manager.go (1)
  • NewManager (32-45)
pkg/config/provider.go (2)
  • NewDefaultProvider (233-237)
  • NewCLIProvider (51-55)
test/integration/tasks/helpers/setup.go (1)
test/helpers/repo.go (1)
  • SetupTestRepos (14-28)
test/integration/database/sqlite_specific_test.go (1)
test/helpers/database.go (1)
  • SetupTestDatabase (406-421)
pkg/config/definition/schema.go (1)
pkg/config/definition/field.go (2)
  • Registry (21-23)
  • FieldDef (10-18)
🪛 Checkov (3.2.334)
examples/memory-mode/edge-deployment/Dockerfile.edge

[low] 1-16: Ensure that a user for the container has been created

(CKV_DOCKER_3)

🪛 dotenv-linter (4.0.0)
examples/distributed-mode/.env.example

[warning] 5-5: [UnorderedKey] The REDIS_ADDRESS key should go before the TEMPORAL_ADDRESS key

(UnorderedKey)


[warning] 6-6: [UnorderedKey] The OPENAI_API_KEY key should go before the REDIS_ADDRESS key

(UnorderedKey)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: test
  • GitHub Check: Container Security Scan
  • GitHub Check: Analyze (go)
  • GitHub Check: Security Scan (gosec)
  • GitHub Check: Test Coverage

Comment thread docs/docs.go
Comment thread engine/infra/cache/mod_test.go Outdated
Comment thread engine/infra/server/dependencies.go Outdated
Comment thread engine/infra/sqlite/migrations.go
Comment thread examples/persistent-mode/.env.example
Comment thread test/helpers/server/server.go
Comment thread test/integration/database/multi_driver_test.go Outdated
Comment thread test/integration/database/sqlite_specific_test.go Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
engine/task/exec/runner.go (1)

96-144: Consider extracting validation logic (optional refactor).

The Prepare method is within the 50-line limit but performs multiple operations. Consider extracting the runner validation block (lines 100-108) into a separate validateRunner() helper method to improve maintainability and reduce cognitive complexity.

Example refactor:

+func (r *Runner) validateRunner() error {
+	if r.state == nil {
+		return ErrStateRequired
+	}
+	if r.repo == nil {
+		return ErrRepositoryRequired
+	}
+	if r.store == nil {
+		return ErrResourceStoreRequired
+	}
+	return nil
+}
+
 func (r *Runner) Prepare(ctx context.Context, req ExecuteRequest) (*PreparedExecution, error) {
 	if ctx == nil {
 		return nil, fmt.Errorf("context is required")
 	}
-	if r.state == nil {
-		return nil, ErrStateRequired
-	}
-	if r.repo == nil {
-		return nil, ErrRepositoryRequired
-	}
-	if r.store == nil {
-		return nil, ErrResourceStoreRequired
+	if err := r.validateRunner(); err != nil {
+		return nil, err
 	}
 	if strings.TrimSpace(req.TaskID) == "" {
 		return nil, ErrTaskIDRequired
 	}
pkg/config/config.go (1)

1444-1449: Update embedded Redis env prefixes.

These env tags still advertise the deprecated REDIS_STANDALONE_* prefix; operators following the new embedded naming (REDIS_EMBEDDED_*) will find their settings ignored.

-	Enabled            bool          `koanf:"enabled"              json:"enabled"              yaml:"enabled"              mapstructure:"enabled"              env:"REDIS_STANDALONE_PERSISTENCE_ENABLED"`
-	DataDir            string        `koanf:"data_dir"             json:"data_dir"             yaml:"data_dir"             mapstructure:"data_dir"             env:"REDIS_STANDALONE_PERSISTENCE_DATA_DIR"`
-	SnapshotInterval   time.Duration `koanf:"snapshot_interval"    json:"snapshot_interval"    yaml:"snapshot_interval"    mapstructure:"snapshot_interval"    env:"REDIS_STANDALONE_PERSISTENCE_SNAPSHOT_INTERVAL"`
-	SnapshotOnShutdown bool          `koanf:"snapshot_on_shutdown" json:"snapshot_on_shutdown" yaml:"snapshot_on_shutdown" mapstructure:"snapshot_on_shutdown" env:"REDIS_STANDALONE_PERSISTENCE_SNAPSHOT_ON_SHUTDOWN"`
-	RestoreOnStartup   bool          `koanf:"restore_on_startup"   json:"restore_on_startup"   yaml:"restore_on_startup"   mapstructure:"restore_on_startup"   env:"REDIS_STANDALONE_PERSISTENCE_RESTORE_ON_STARTUP"`
+	Enabled            bool          `koanf:"enabled"              json:"enabled"              yaml:"enabled"              mapstructure:"enabled"              env:"REDIS_EMBEDDED_PERSISTENCE_ENABLED"`
+	DataDir            string        `koanf:"data_dir"             json:"data_dir"             yaml:"data_dir"             mapstructure:"data_dir"             env:"REDIS_EMBEDDED_PERSISTENCE_DATA_DIR"`
+	SnapshotInterval   time.Duration `koanf:"snapshot_interval"    json:"snapshot_interval"    yaml:"snapshot_interval"    mapstructure:"snapshot_interval"    env:"REDIS_EMBEDDED_PERSISTENCE_SNAPSHOT_INTERVAL"`
+	SnapshotOnShutdown bool          `koanf:"snapshot_on_shutdown" json:"snapshot_on_shutdown" yaml:"snapshot_on_shutdown" mapstructure:"snapshot_on_shutdown" env:"REDIS_EMBEDDED_PERSISTENCE_SNAPSHOT_ON_SHUTDOWN"`
+	RestoreOnStartup   bool          `koanf:"restore_on_startup"   json:"restore_on_startup"   yaml:"restore_on_startup"   mapstructure:"restore_on_startup"   env:"REDIS_EMBEDDED_PERSISTENCE_RESTORE_ON_STARTUP"`

As per coding guidelines

♻️ Duplicate comments (1)
docs/docs.go (1)

1870-1870: Update source Swagger annotations and regenerate docs instead of editing generated file.

This issue was already flagged in a previous review. The file docs/docs.go is auto-generated by swaggo/swag, and manual edits will be overwritten when swag init runs.

Update the @Failure 503 annotations in the source handler files:

  • engine/workflow/router/stream.go (around line 168)
  • engine/task/router/stream.go (around line 107)
  • engine/agent/router/stream.go (around line 119)

Then run swag init to regenerate this file.

As per coding guidelines.

Also applies to: 2074-2074, 2278-2278, 2357-2357, 2474-2474, 2573-2573, 2672-2672, 2771-2771, 2897-2897, 3023-3023, 10656-10656, 10792-10792, 10960-10960

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between bce1809 and f4cadb5.

⛔ Files ignored due to path filters (45)
  • README.md is excluded by !**/*.md
  • cli/help/global-flags.md is excluded by !**/*.md
  • docs/content/docs/architecture/embedded-temporal.mdx is excluded by !**/*.mdx
  • docs/content/docs/architecture/overview.mdx is excluded by !**/*.mdx
  • docs/content/docs/cli/compozy-start.mdx is excluded by !**/*.mdx
  • docs/content/docs/configuration/mode-configuration.mdx is excluded by !**/*.mdx
  • docs/content/docs/configuration/redis.mdx is excluded by !**/*.mdx
  • docs/content/docs/configuration/temporal.mdx is excluded by !**/*.mdx
  • docs/content/docs/core/mcp/migration-notes.mdx is excluded by !**/*.mdx
  • docs/content/docs/deployment/distributed-mode.mdx is excluded by !**/*.mdx
  • docs/content/docs/deployment/docker.mdx is excluded by !**/*.mdx
  • docs/content/docs/deployment/memory-mode.mdx is excluded by !**/*.mdx
  • docs/content/docs/deployment/persistent-mode.mdx is excluded by !**/*.mdx
  • docs/content/docs/deployment/production.mdx is excluded by !**/*.mdx
  • docs/content/docs/deployment/temporal-modes.mdx is excluded by !**/*.mdx
  • docs/content/docs/examples/persistent-mode.mdx is excluded by !**/*.mdx
  • docs/content/docs/faq.mdx is excluded by !**/*.mdx
  • docs/content/docs/troubleshooting/common-issues.mdx is excluded by !**/*.mdx
  • docs/content/docs/troubleshooting/temporal.mdx is excluded by !**/*.mdx
  • docs/swagger.json is excluded by !**/*.json, !docs/swagger.*
  • docs/swagger.yaml is excluded by !**/*.yaml, !docs/swagger.*
  • examples/configs/distributed-mode.yaml is excluded by !**/*.yaml
  • examples/configs/persistent-mode.yaml is excluded by !**/*.yaml
  • examples/persistent-mode/compozy.yaml is excluded by !**/*.yaml
  • schemas/cache.json is excluded by !**/*.json
  • schemas/compozy.json is excluded by !**/*.json
  • schemas/config-redis.json is excluded by !**/*.json
  • schemas/config-temporal.json is excluded by !**/*.json
  • schemas/config.json is excluded by !**/*.json
  • tasks/docs/_task-template.md is excluded by !**/*.md
  • tasks/prd-modes-refac/_task_1.md is excluded by !**/*.md
  • tasks/prd-modes-refac/_task_2.md is excluded by !**/*.md
  • tasks/prd-modes-refac/_task_3.md is excluded by !**/*.md
  • tasks/prd-modes-refac/_task_4.md is excluded by !**/*.md
  • tasks/prd-modes-refac/_task_5.md is excluded by !**/*.md
  • tasks/prd-modes-refac/_task_6.md is excluded by !**/*.md
  • tasks/prd-modes-refac/_task_7.md is excluded by !**/*.md
  • tasks/prd-modes-refac/_tasks.md is excluded by !**/*.md
  • tasks/prd-modes-refac/_techspec.md is excluded by !**/*.md
  • test/fixtures/embedded/persistence.go is excluded by !**/fixtures/**
  • test/fixtures/embedded/sample_resource.yaml is excluded by !**/*.yaml, !**/fixtures/**
  • test/fixtures/embedded/streaming.go is excluded by !**/fixtures/**
  • test/fixtures/embedded/workflows/stateful-workflow.yaml is excluded by !**/*.yaml, !**/fixtures/**
  • test/fixtures/embedded/workflows/test-workflow.yaml is excluded by !**/*.yaml, !**/fixtures/**
  • test/integration/README.md is excluded by !**/*.md
📒 Files selected for processing (24)
  • docs/docs.go (15 hunks)
  • engine/agent/router/stream.go (1 hunks)
  • engine/infra/cache/miniredis_embedded.go (6 hunks)
  • engine/infra/cache/miniredis_embedded_test.go (5 hunks)
  • engine/infra/cache/mod.go (4 hunks)
  • engine/infra/cache/mod_test.go (2 hunks)
  • engine/infra/cache/snapshot_manager_test.go (4 hunks)
  • engine/infra/server/dependencies.go (7 hunks)
  • engine/infra/server/mcp_test.go (3 hunks)
  • engine/infra/server/temporal_resolver_test.go (2 hunks)
  • engine/infra/sqlite/migrations.go (2 hunks)
  • engine/task/exec/runner.go (1 hunks)
  • engine/task/router/stream.go (1 hunks)
  • engine/tool/builtin/calltask/schema.go (1 hunks)
  • engine/webhook/idem_memory.go (1 hunks)
  • engine/worker/embedded/config.go (2 hunks)
  • engine/worker/embedded/namespace_test.go (1 hunks)
  • engine/workflow/router/stream.go (1 hunks)
  • examples/persistent-mode/.env.example (1 hunks)
  • pkg/config/config.go (10 hunks)
  • pkg/config/config_test.go (12 hunks)
  • pkg/config/definition/schema.go (7 hunks)
  • pkg/config/loader.go (5 hunks)
  • pkg/config/loader_test.go (4 hunks)
🧰 Additional context used
📓 Path-based instructions (15)
**/*.go

📄 CodeRabbit inference engine (.cursor/rules/api-standards.mdc)

**/*.go: Return properly structured error responses
Use middleware for cross-cutting concerns (e.g., logging, auth, rate limiting)
Implement proper authentication and authorization in the API
Apply rate limiting and request validation
Version API routes under the prefix /api/v0/
Use gin-gonic/gin for HTTP APIs
Ensure consistent response formats across all endpoints
Use appropriate HTTP status codes (200, 201, 400, 401, 403, 404, 500)
Return JSON responses with a consistent error structure
Update Swagger annotations for all API changes
Generate Swagger docs served at /swagger/index.html using swaggo/swag
Include request and response examples in Swagger annotations
Document all parameters, headers, and error responses in Swagger
Success response body should contain fields: data and message ("Success")
Error response body should contain fields: error and details

**/*.go: Retrieve the logger via logger.FromContext(ctx) inside runtime code (handlers, services, workers)
Retrieve configuration via config.FromContext(ctx) inside runtime code (handlers, services, workers)
Attach *config.Manager at process edges using config.ContextWithManager(ctx, mgr)
Build the logger with logger.SetupLogger(...) at startup and attach with logger.ContextWithLogger(ctx, log)
For HTTP servers, ensure request contexts inherit BOTH manager and logger via middleware
Do not pass loggers via function parameters or dependency injection; always use context-backed retrieval
Do not use a global configuration singleton; read config from context
CLI/root flow: parse flags → construct sources → mgr.Load(...) → attach manager to ctx → setup logger honoring cfg.CLI.Debug/Quiet → attach logger to ctx → propagate ctx
Server startup should use the CLI-provided ctx and add middleware that sets c.Request = c.Request.WithContext(logger.ContextWithLogger(config.ContextWithManager(c.Request.Context(), mgr), log))
Optionally set http.Server.BaseContext to a parent context carrying manager and logger so all req...

Files:

  • engine/workflow/router/stream.go
  • engine/tool/builtin/calltask/schema.go
  • engine/infra/sqlite/migrations.go
  • pkg/config/config_test.go
  • engine/task/router/stream.go
  • engine/infra/server/temporal_resolver_test.go
  • engine/worker/embedded/config.go
  • engine/infra/server/mcp_test.go
  • engine/infra/cache/miniredis_embedded_test.go
  • engine/infra/cache/miniredis_embedded.go
  • engine/webhook/idem_memory.go
  • engine/infra/cache/mod.go
  • engine/infra/cache/snapshot_manager_test.go
  • engine/agent/router/stream.go
  • pkg/config/loader_test.go
  • engine/task/exec/runner.go
  • engine/infra/server/dependencies.go
  • engine/worker/embedded/namespace_test.go
  • engine/infra/cache/mod_test.go
  • docs/docs.go
  • pkg/config/loader.go
  • pkg/config/definition/schema.go
  • pkg/config/config.go
**/!(*_test).go

📄 CodeRabbit inference engine (.cursor/rules/magic-numbers.mdc)

**/!(*_test).go: NEVER introduce magic numbers in runtime Go code; replace unexplained numeric literals with named constants or configuration
Operator-tunable values MUST be sourced from configuration as defined in @.cursor/rules/global-config.mdc
Fetch configuration via config.FromContext(ctx); do not use global singletons
Promote tunable values (timeouts, deadlines, polling intervals, retry/backoff counts and factors, concurrency limits, queue sizes, buffer/payload limits, behavior thresholds) to configuration

In runtime code, properly inherit context; never use context.Background() in code paths

In runtime code paths, inherit context properly; never use context.Background()

In runtime code paths, never use context.Background(); properly inherit context

In runtime code, properly inherit context; never use context.Background()

Files:

  • engine/workflow/router/stream.go
  • engine/tool/builtin/calltask/schema.go
  • engine/infra/sqlite/migrations.go
  • engine/task/router/stream.go
  • engine/worker/embedded/config.go
  • engine/infra/cache/miniredis_embedded.go
  • engine/webhook/idem_memory.go
  • engine/infra/cache/mod.go
  • engine/agent/router/stream.go
  • engine/task/exec/runner.go
  • engine/infra/server/dependencies.go
  • docs/docs.go
  • pkg/config/loader.go
  • pkg/config/definition/schema.go
  • pkg/config/config.go
engine/{agent,task,task2,tool,workflow,runtime,llm,memory,memorycfg,knowledge,model,mcp,webhook,attachment,resources,auth,autoload,project,schema,worker}/**/*.go

📄 CodeRabbit inference engine (.cursor/rules/architecture.mdc)

engine/{agent,task,task2,tool,workflow,runtime,llm,memory,memorycfg,knowledge,model,mcp,webhook,attachment,resources,auth,autoload,project,schema,worker}/**/*.go: Application Layer (engine/): implement domain-specific business logic and ports; organize by domain with uc/ and router/ subpackages
Port interfaces (e.g., repositories, external services) are defined in Application Layer packages where they are used
Application layer depends inward: Application → Domain; avoid depending on infrastructure

Files:

  • engine/workflow/router/stream.go
  • engine/tool/builtin/calltask/schema.go
  • engine/task/router/stream.go
  • engine/worker/embedded/config.go
  • engine/webhook/idem_memory.go
  • engine/agent/router/stream.go
  • engine/task/exec/runner.go
  • engine/worker/embedded/namespace_test.go
engine/*/router/**/*.go

📄 CodeRabbit inference engine (.cursor/rules/architecture.mdc)

Routers contain HTTP handling only (transport mapping, DTOs); no business logic

Files:

  • engine/workflow/router/stream.go
  • engine/task/router/stream.go
  • engine/agent/router/stream.go
{engine,pkg,cli}/**/*.go

📄 CodeRabbit inference engine (.cursor/rules/architecture.mdc)

Context as the first parameter for I/O or long-running operations; always propagate and handle cancellation

Files:

  • engine/workflow/router/stream.go
  • engine/tool/builtin/calltask/schema.go
  • engine/infra/sqlite/migrations.go
  • pkg/config/config_test.go
  • engine/task/router/stream.go
  • engine/infra/server/temporal_resolver_test.go
  • engine/worker/embedded/config.go
  • engine/infra/server/mcp_test.go
  • engine/infra/cache/miniredis_embedded_test.go
  • engine/infra/cache/miniredis_embedded.go
  • engine/webhook/idem_memory.go
  • engine/infra/cache/mod.go
  • engine/infra/cache/snapshot_manager_test.go
  • engine/agent/router/stream.go
  • pkg/config/loader_test.go
  • engine/task/exec/runner.go
  • engine/infra/server/dependencies.go
  • engine/worker/embedded/namespace_test.go
  • engine/infra/cache/mod_test.go
  • pkg/config/loader.go
  • pkg/config/definition/schema.go
  • pkg/config/config.go
engine/infra/**/*.go

📄 CodeRabbit inference engine (.cursor/rules/architecture.mdc)

engine/infra/**/*.go: Infrastructure Layer (engine/infra): implement adapters for DB, cache, HTTP, storage, monitoring; must implement Application Layer interfaces
Adapter implementations belong in Infrastructure Layer and must implement Application Layer interfaces (no business logic leakage)
Infrastructure depends inward: Infrastructure → Application → Domain; avoid imports from cli and cross-infra coupling

Files:

  • engine/infra/sqlite/migrations.go
  • engine/infra/server/temporal_resolver_test.go
  • engine/infra/server/mcp_test.go
  • engine/infra/cache/miniredis_embedded_test.go
  • engine/infra/cache/miniredis_embedded.go
  • engine/infra/cache/mod.go
  • engine/infra/cache/snapshot_manager_test.go
  • engine/infra/server/dependencies.go
  • engine/infra/cache/mod_test.go
pkg/config/**/*_test.go

📄 CodeRabbit inference engine (.cursor/rules/global-config.mdc)

Add or extend tests under pkg/config/*_test.go when introducing validation or complex defaults

Files:

  • pkg/config/config_test.go
  • pkg/config/loader_test.go
**/*_test.go

📄 CodeRabbit inference engine (.cursor/rules/logger-config.mdc)

**/*_test.go: In tests, set up configuration with config.Initialize or config.NewManager(...).Load(...) and attach via config.ContextWithManager
In tests, prefer logger.NewForTests() and attach with logger.ContextWithLogger
In tests, mock or stub external tools/services; do not introduce DI of logger/config into code under test

**/*_test.go: Prefer local test constants (e.g., const testTimeout = 5 * time.Second) in tests
Inline trivial literals in tests when intent is clear
Do not duplicate production constants in tests; import them or assert relative behavior

**/*_test.go: All tests pass and follow the established testing patterns
Code is well-tested with both unit and integration tests
Tests should follow the t.Run("Should...") subtest naming pattern
Ensure adequate test coverage

**/*_test.go: All Go tests must use t.Run("Should describe behavior", ...) subtests for each behavior
Use stretchr/testify for assertions and mocks in tests
Do not use testify suite patterns (no suite.Suite embedding or suite-based structures)
Do not use suite methods like s.Equal(), s.NoError(), or s.T()
Avoid weak assertions like assert.Error(t, err); use specific error validation instead
Prefer specific error assertions like assert.ErrorContains and assert.ErrorAs for validating errors
Unit tests should be placed alongside implementation files as *_test.go
Use testify/mock for mocking external dependencies or complex interfaces

In tests, never use context.Background(); use t.Context() instead

Aim for 80%+ test coverage on business logic; write focused, isolated tests

**/*_test.go: Use stretchr/testify for assertions and mocks; import as github.com/stretchr/testify/assert and github.com/stretchr/testify/mock; replace custom mocks with testify/mock
Use project test helpers (utils.SetupTest, utils.SetupFixture, etc.) in tests

In tests, never use context.Background(); use t.Context()

Files:

  • pkg/config/config_test.go
  • engine/infra/server/temporal_resolver_test.go
  • engine/infra/server/mcp_test.go
  • engine/infra/cache/miniredis_embedded_test.go
  • engine/infra/cache/snapshot_manager_test.go
  • pkg/config/loader_test.go
  • engine/worker/embedded/namespace_test.go
  • engine/infra/cache/mod_test.go
pkg/**/*.go

📄 CodeRabbit inference engine (.cursor/rules/architecture.mdc)

Shared Packages (pkg): provide framework-level utilities (config, logging, templates, schema generation); must not contain business logic

Files:

  • pkg/config/config_test.go
  • pkg/config/loader_test.go
  • pkg/config/loader.go
  • pkg/config/definition/schema.go
  • pkg/config/config.go
pkg/config/**/*.go

📄 CodeRabbit inference engine (.cursor/rules/architecture.mdc)

Global configuration resides in pkg/config; expose retrieval via context (config.FromContext) and provide defaults; avoid global singletons

Files:

  • pkg/config/config_test.go
  • pkg/config/loader_test.go
  • pkg/config/loader.go
  • pkg/config/definition/schema.go
  • pkg/config/config.go
docs/**/*.go

📄 CodeRabbit inference engine (docs/.cursor/rules/review-checklist.mdc)

docs/**/*.go: Code must be formatted with go fmt
All linter warnings must be addressed
Error handling must follow project patterns
Security considerations must be addressed (e.g., no exposed secrets or unvalidated inputs)
Errors must be handled appropriately and with context
Interfaces must be used appropriately to define behavior
Code must pass all linter checks
Code must be secure and performant
Dependencies must be injected properly
Context must be propagated correctly
Hardcoded values that should be configurable must be avoided
Missing context propagation in functions that make external calls must be addressed
Performance issues like unnecessary allocations or inefficient algorithms must be avoided

docs/**/*.go: Use section comments with dashes for visual separation in Go code, formatted as:
// -----------------------------------------------------------------------------
// Section Name
// -----------------------------------------------------------------------------

Files:

  • docs/docs.go
pkg/config/loader.go

📄 CodeRabbit inference engine (.cursor/rules/global-config.mdc)

pkg/config/loader.go: Implement cross-field validation in validateCustom when struct tag validation is insufficient
Extend validateCustom for cross-field constraints in new categories when struct tags are insufficient

Files:

  • pkg/config/loader.go
pkg/config/definition/schema.go

📄 CodeRabbit inference engine (.cursor/rules/global-config.mdc)

pkg/config/definition/schema.go: Use pkg/config/definition/schema.go as the single source of truth for configuration by registering fields in the registry
Add new property by registering it with registry.Register(&FieldDef{Path, Default, CLIFlag, EnvVar, Type, Help}); keep path naming category.property_name (snake_case)
Register all fields of a new category in register

Fields and include it in CreateRegistry()
Config path format must be section.snake_case_property when registering fields
CLI flags in registry must use kebab-case (CLIFlag)
Durations should use time.Duration and defaults in the registry must be time.Duration values

Files:

  • pkg/config/definition/schema.go
{pkg/config/config.go,pkg/config/definition/schema.go}

📄 CodeRabbit inference engine (.cursor/rules/global-config.mdc)

Environment variable names must be UPPER_SNAKE_CASE with domain prefixes (e.g., SERVER_, DB_, RUNTIME_, CLI uses COMPOZY_)

Files:

  • pkg/config/definition/schema.go
  • pkg/config/config.go
pkg/config/config.go

📄 CodeRabbit inference engine (.cursor/rules/global-config.mdc)

pkg/config/config.go: Add the new field to the typed config struct with tags: koanf/json/yaml/mapstructure; include env tag when applicable; add validate tag if needed; use SensitiveString or sensitive:"true" for secrets
Map from registry to typed struct in build

Config using getString/getInt/getBool/getDuration/getInt64/getStringSlice
For secrets, prefer SensitiveString type or sensitive:"true" tag to enable automatic JSON redaction
When creating a new category, define type
Config struct with full tagging and validation
Add the new section to the root Config with koanf/json/yaml/mapstructure tags
Implement build
Config(registry *definition.Registry) to map defaults from the registry to the typed struct
Always include koanf, json, yaml, and mapstructure tags on config struct fields; include env when applicable

Files:

  • pkg/config/config.go
🧬 Code graph analysis (12)
pkg/config/config_test.go (4)
pkg/config/resolver.go (5)
  • ModeMemory (7-7)
  • ResolveMode (20-28)
  • ModePersistent (8-8)
  • ModeDistributed (9-9)
  • ModeRemoteTemporal (11-11)
pkg/config/config.go (1)
  • Default (2023-2025)
pkg/config/loader.go (1)
  • NewService (54-67)
pkg/config/provider.go (2)
  • NewDefaultProvider (233-237)
  • NewCLIProvider (51-55)
engine/worker/embedded/config.go (1)
pkg/config/config.go (1)
  • EmbeddedTemporalConfig (592-624)
engine/infra/server/mcp_test.go (1)
pkg/config/resolver.go (2)
  • ModeMemory (7-7)
  • ModeDistributed (9-9)
engine/infra/cache/miniredis_embedded_test.go (1)
engine/infra/cache/miniredis_embedded.go (2)
  • MiniredisEmbedded (18-23)
  • NewMiniredisEmbedded (70-111)
engine/infra/cache/mod.go (3)
pkg/config/resolver.go (3)
  • ModeMemory (7-7)
  • ModePersistent (8-8)
  • ModeDistributed (9-9)
engine/infra/cache/miniredis_embedded.go (2)
  • MiniredisEmbedded (18-23)
  • NewMiniredisEmbedded (70-111)
pkg/config/config.go (2)
  • Config (58-148)
  • RedisConfig (1322-1434)
engine/infra/cache/snapshot_manager_test.go (2)
pkg/config/config.go (3)
  • EmbeddedRedisConfig (1437-1440)
  • RedisConfig (1322-1434)
  • Config (58-148)
engine/infra/cache/miniredis_embedded.go (1)
  • NewMiniredisEmbedded (70-111)
pkg/config/loader_test.go (3)
pkg/config/resolver.go (3)
  • ModeMemory (7-7)
  • ModeDistributed (9-9)
  • ModePersistent (8-8)
pkg/config/config.go (1)
  • Default (2023-2025)
pkg/config/loader.go (1)
  • NewService (54-67)
engine/infra/server/dependencies.go (4)
pkg/config/resolver.go (2)
  • ModeMemory (7-7)
  • ModePersistent (8-8)
engine/worker/embedded/server.go (1)
  • Server (30-38)
engine/worker/embedded/config.go (1)
  • Config (37-37)
pkg/config/config.go (1)
  • Config (58-148)
engine/infra/cache/mod_test.go (5)
pkg/logger/mod.go (2)
  • ContextWithLogger (39-41)
  • NewForTests (199-201)
pkg/config/provider.go (2)
  • NewDefaultProvider (233-237)
  • NewEnvProvider (21-23)
pkg/config/context.go (1)
  • ContextWithManager (19-21)
pkg/config/resolver.go (3)
  • ModeMemory (7-7)
  • ModePersistent (8-8)
  • ModeDistributed (9-9)
engine/infra/cache/mod.go (1)
  • SetupCache (53-78)
pkg/config/loader.go (3)
engine/worker/embedded/config.go (1)
  • Config (37-37)
pkg/config/config.go (2)
  • Config (58-148)
  • EmbeddedTemporalConfig (592-624)
pkg/config/resolver.go (4)
  • ModeMemory (7-7)
  • ModePersistent (8-8)
  • ModeDistributed (9-9)
  • ModeRemoteTemporal (11-11)
pkg/config/definition/schema.go (1)
pkg/config/definition/field.go (2)
  • Registry (21-23)
  • FieldDef (10-18)
pkg/config/config.go (1)
pkg/config/resolver.go (2)
  • ModeMemory (7-7)
  • ModePersistent (8-8)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: test
  • GitHub Check: Analyze (go)
  • GitHub Check: Container Security Scan
  • GitHub Check: Security Scan (gosec)
  • GitHub Check: Test Coverage
🔇 Additional comments (41)
examples/persistent-mode/.env.example (1)

1-2: Helpful comment successfully added for consistency.

The previous review feedback has been addressed—the helpful comment guiding users to populate credentials is now present and aligns with the pattern established in the memory-mode example.

engine/tool/builtin/calltask/schema.go (1)

10-10: Terminology update aligns with mode refactoring.

The description change from "standalone" to "embedded" is consistent with the PR's shift toward the new modes architecture.

To confirm consistency, verify that similar terminology updates (if any) have been applied to related schema descriptions or documentation across the codebase. If there are other references to "standalone task" or similar patterns in schema definitions or API documentation, please ensure they have also been updated to reflect the new mode semantics.

engine/infra/sqlite/migrations.go (1)

40-52: Defer pattern correctly addresses previous concurrency concern.

The mutex initialization is now properly guarded with a defer block (lines 41–44) that guarantees cleanup even if goose.SetDialect or goose.UpContext panic. BaseFS and the mutex are always restored regardless of early returns or panic, preventing deadlock on subsequent calls. Context is correctly propagated to goose.UpContext at line 49.

engine/task/exec/runner.go (4)

35-40: LGTM! Proper dependency injection for resource store.

The addition of the store field properly extends the Runner to support embedded mode execution with resource store access. The comment update clearly indicates the execution semantics.


65-67: LGTM! Constructor properly initializes dependencies.

The updated constructor signature correctly accepts and initializes the new resource store dependency.


106-108: LGTM! Proper validation for the new dependency.

The nil check for r.store follows the same pattern as other dependency validations and ensures the runner is properly initialized.


173-211: LGTM! Proper resource store usage.

The r.store field is correctly utilized in both loadTaskConfig and hydrateAgentConfig methods. Context propagation is correct, and errors are properly wrapped with contextual information.

engine/webhook/idem_memory.go (1)

10-10: Terminology update looks good

Comment now matches the embedded/dev mode nomenclature introduced elsewhere.

engine/worker/embedded/namespace_test.go (1)

69-69: Fixture matches embedded mode

Switching the test namespace to “embedded” keeps the test configuration in step with the new mode naming.

engine/worker/embedded/config.go (1)

35-37: Alias keeps embedded worker aligned

Adopting the alias to pkgconfig.EmbeddedTemporalConfig removes duplication and lets this package track the canonical struct definition.

engine/task/router/stream.go (1)

107-107: Doc wording is consistent

The 503 description now matches the worker-focused terminology used across the streaming APIs.

engine/agent/router/stream.go (1)

119-119: Doc terminology aligns

Updated 503 description matches the worker-focused language adopted elsewhere.

engine/workflow/router/stream.go (1)

168-168: LGTM! Documentation improvement.

The updated description "Worker unavailable" is more specific and accurately reflects the primary 503 failure case when ensureWorkerReady returns false (line 135). This change aligns well with the mode-based architecture refactoring mentioned in the PR objectives.

engine/infra/server/temporal_resolver_test.go (1)

12-24: Embedded Temporal resolver coverage stays accurate

Renaming the test and invoking maybeStartEmbeddedTemporal keeps the resolver spec in sync with the new embedded startup flow while still validating the distributed skip path. Nice alignment.

engine/infra/server/mcp_test.go (1)

15-54: Mode constants now mirror production semantics

Using config.ModeMemory and config.ModeDistributed in these scenarios keeps the MCP proxy embedding tests aligned with the new mode API and avoids string drift. Looks good.

engine/infra/cache/snapshot_manager_test.go (1)

63-157: Embedded Redis snapshot flow validated end-to-end

Switching the tests to EmbeddedRedisConfig and NewMiniredisEmbedded exercises the new persistence wiring all the way through shutdown/restore, so coverage remains comprehensive after the rename.

engine/infra/cache/mod_test.go (1)

15-97: Cache mode tests now match embedded/persistent semantics

The shared helper plus t.Run scenarios clearly assert memory, persistent, and distributed behaviors against the updated config toggles. This keeps coverage consistent with the revised cache setup.

engine/infra/cache/miniredis_embedded_test.go (1)

17-152: Embedded miniredis tests track the renamed implementation

Updating the helpers and scenarios to NewMiniredisEmbedded ensures lifecycle and operation checks remain pointed at the production wrapper after the rename. Coverage stays solid.

pkg/config/config_test.go (5)

36-37: LGTM! Default mode correctly updated to memory.

The test properly verifies that the default configuration mode is ModeMemory and that ResolveMode correctly resolves to this default.


130-140: LGTM! Memory mode SQLite driver resolution test.

The test correctly verifies that when global mode is set to ModeMemory, the effective database driver resolves to SQLite.


142-184: LGTM! Comprehensive mode validation tests.

The table-driven test properly covers:

  • Valid modes (empty/memory/persistent/distributed)
  • Deprecated standalone mode with helpful error messages
  • Invalid mode values with appropriate errors
  • Mode inheritance when empty

262-301: LGTM! Embedded Temporal mode tests properly updated.

Tests correctly verify memory and persistent mode behavior with embedded Temporal configuration, including host/port overrides.


671-753: LGTM! MCP proxy mode validation comprehensive.

The test suite properly validates:

  • Mode inheritance from global config
  • Explicit memory/persistent/distributed modes
  • Deprecated standalone rejection
  • Port requirements for embedded modes
engine/infra/cache/mod.go (3)

80-94: LGTM! Memory mode properly disables persistence.

The function correctly:

  • Validates Redis configuration presence
  • Explicitly disables persistence for memory mode
  • Logs both current and previous persistence state
  • Routes to unified embedded cache setup

96-117: LGTM! Persistent mode properly enables persistence with defaults.

The function correctly:

  • Validates Redis configuration presence
  • Enables persistence if not already enabled
  • Applies default data directory when missing
  • Logs persistence configuration details

119-150: LGTM! Unified embedded cache setup is well-structured.

The function properly:

  • Creates embedded miniredis instance
  • Wraps with Redis facade, lock manager, and notification system
  • Handles cleanup on failure paths
  • Logs initialization with mode and persistence state
pkg/config/loader.go (4)

376-396: LGTM! Global mode validation with clear migration guidance.

The validation correctly:

  • Accepts empty, memory, persistent, and distributed modes
  • Rejects deprecated standalone with helpful migration guidance
  • Provides clear error messages for invalid values

430-454: LGTM! Temporal mode validation properly handles embedded modes.

The validation correctly:

  • Routes remote mode to host/port validation
  • Routes memory/persistent to embedded config validation
  • Rejects deprecated standalone with clear guidance
  • Provides comprehensive error messages

548-585: LGTM! Redis mode validation handles embedded persistence.

The validation correctly:

  • Accepts empty, memory, persistent, and distributed modes
  • Rejects deprecated standalone with migration guidance
  • Validates embedded persistence settings when enabled
  • Checks data directory and snapshot interval requirements

637-673: LGTM! MCP proxy mode validation comprehensive.

The validation correctly:

  • Separates mode validation into dedicated function
  • Validates port requirements for embedded modes
  • Rejects deprecated standalone mode
  • Provides clear error messages
pkg/config/loader_test.go (3)

118-192: LGTM! MCP proxy mode validation tests comprehensive.

The tests properly cover:

  • Inheritance from global mode
  • Explicit memory/persistent/distributed modes
  • Deprecated standalone rejection with error substrings
  • Invalid value rejection

194-221: LGTM! Port requirement tests for embedded modes.

The tests correctly verify that memory and persistent modes require explicit non-zero ports, with appropriate error message validation.


223-309: LGTM! Global and component mode validation refactored to table-driven.

The tests are well-structured with:

  • Clear test case naming
  • Proper error substring validation
  • Coverage of valid, invalid, and deprecated modes
  • Consistent use of mode constants
engine/infra/cache/miniredis_embedded.go (2)

15-23: LGTM! Type renaming to MiniredisEmbedded is appropriate.

The renaming from MiniredisStandalone to MiniredisEmbedded better reflects the new terminology and aligns with the embedded mode semantics across the codebase.


70-87: LGTM! Improved mode logging.

The constructor now properly logs the effective Redis mode from configuration, providing better visibility into which mode is active.

engine/infra/server/dependencies.go (2)

139-169: LGTM! Database validation properly extracts and logs mode.

The validation correctly:

  • Extracts mode with default to memory
  • Includes mode in log messages
  • Warns about SQLite limitations with mode context
  • Provides clear recommendations

389-431: LGTM! Embedded Temporal startup properly refactored.

The function correctly:

  • Uses EffectiveTemporalMode to determine mode
  • Only starts for memory/persistent modes
  • Logs mode throughout startup
  • Provides development/testing warning with mode context
pkg/config/definition/schema.go (4)

47-57: LGTM! Global mode field properly registered.

The field definition correctly:

  • Sets default to "memory"
  • Uses appropriate CLI flag and env var
  • Provides clear help text describing all three modes

2213-2222: LGTM! Redis mode field properly added.

The field definition correctly:

  • Defaults to empty for inheritance
  • Uses appropriate CLI flag and env var
  • Clearly describes mode inheritance behavior

2419-2419: LGTM! CLI mode flag renamed to avoid collision.

Renaming the CLI flag from "mode" to "cli-mode" prevents collision with the global mode flag, which is the correct approach.


2896-2900: LGTM! MCP proxy mode default updated to memory.

The default mode change from standalone to memory aligns with the new mode semantics, and the help text clearly describes the embedded vs distributed behavior.

Comment thread docs/docs.go
Comment thread engine/infra/server/dependencies.go Outdated
Comment thread pkg/config/config.go
Comment thread pkg/config/config.go
@@ -572,46 +581,46 @@ type TemporalConfig struct {
// Default: "compozy-tasks"
TaskQueue string `koanf:"task_queue" env:"TEMPORAL_TASK_QUEUE" json:"task_queue" yaml:"task_queue" mapstructure:"task_queue"`
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Validate Temporal mode inputs.

The Temporal mode tag now accepts any value; we still only support memory/persistent/distributed, so keep the validator to stop invalid configs from slipping through.

-	Mode string `koanf:"mode" env:"TEMPORAL_MODE" json:"mode" yaml:"mode" mapstructure:"mode" validate:"omitempty"`
+	Mode string `koanf:"mode" env:"TEMPORAL_MODE" json:"mode" yaml:"mode" mapstructure:"mode" validate:"omitempty,oneof=memory persistent distributed"`

As per coding guidelines

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Mode string `koanf:"mode" env:"TEMPORAL_MODE" json:"mode" yaml:"mode" mapstructure:"mode" validate:"omitempty,oneof=memory persistent distributed"`
🤖 Prompt for AI Agents
In pkg/config/config.go around line 558, the Temporal mode tag currently accepts
any value; re-add/restore validation to ensure the mode is one of the supported
values ("memory", "persistent", "distributed") and reject anything else. Update
the config validation function to check the mode (case-insensitive if codebase
prefers) and return a clear error indicating the invalid value and allowed
options; make sure this happens early during config load/validation so invalid
configs fail fast and follow the project error-handling/logging conventions.

Comment thread pkg/config/config.go
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between f4cadb5 and ba19d47.

⛔ Files ignored due to path filters (2)
  • docs/swagger.json is excluded by !**/*.json, !docs/swagger.*
  • docs/swagger.yaml is excluded by !**/*.yaml, !docs/swagger.*
📒 Files selected for processing (8)
  • docs/docs.go (15 hunks)
  • engine/agent/router/stream.go (1 hunks)
  • engine/infra/server/dependencies.go (7 hunks)
  • engine/task/exec/runner.go (2 hunks)
  • engine/task/router/stream.go (1 hunks)
  • engine/workflow/router/stream.go (1 hunks)
  • pkg/config/config.go (10 hunks)
  • pkg/config/loader.go (6 hunks)
🧰 Additional context used
📓 Path-based instructions (12)
**/*.go

📄 CodeRabbit inference engine (.cursor/rules/api-standards.mdc)

**/*.go: Return properly structured error responses
Use middleware for cross-cutting concerns (e.g., logging, auth, rate limiting)
Implement proper authentication and authorization in the API
Apply rate limiting and request validation
Version API routes under the prefix /api/v0/
Use gin-gonic/gin for HTTP APIs
Ensure consistent response formats across all endpoints
Use appropriate HTTP status codes (200, 201, 400, 401, 403, 404, 500)
Return JSON responses with a consistent error structure
Update Swagger annotations for all API changes
Generate Swagger docs served at /swagger/index.html using swaggo/swag
Include request and response examples in Swagger annotations
Document all parameters, headers, and error responses in Swagger
Success response body should contain fields: data and message ("Success")
Error response body should contain fields: error and details

**/*.go: Retrieve the logger via logger.FromContext(ctx) inside runtime code (handlers, services, workers)
Retrieve configuration via config.FromContext(ctx) inside runtime code (handlers, services, workers)
Attach *config.Manager at process edges using config.ContextWithManager(ctx, mgr)
Build the logger with logger.SetupLogger(...) at startup and attach with logger.ContextWithLogger(ctx, log)
For HTTP servers, ensure request contexts inherit BOTH manager and logger via middleware
Do not pass loggers via function parameters or dependency injection; always use context-backed retrieval
Do not use a global configuration singleton; read config from context
CLI/root flow: parse flags → construct sources → mgr.Load(...) → attach manager to ctx → setup logger honoring cfg.CLI.Debug/Quiet → attach logger to ctx → propagate ctx
Server startup should use the CLI-provided ctx and add middleware that sets c.Request = c.Request.WithContext(logger.ContextWithLogger(config.ContextWithManager(c.Request.Context(), mgr), log))
Optionally set http.Server.BaseContext to a parent context carrying manager and logger so all req...

Files:

  • engine/workflow/router/stream.go
  • engine/task/router/stream.go
  • engine/agent/router/stream.go
  • engine/infra/server/dependencies.go
  • docs/docs.go
  • engine/task/exec/runner.go
  • pkg/config/loader.go
  • pkg/config/config.go
**/!(*_test).go

📄 CodeRabbit inference engine (.cursor/rules/magic-numbers.mdc)

**/!(*_test).go: NEVER introduce magic numbers in runtime Go code; replace unexplained numeric literals with named constants or configuration
Operator-tunable values MUST be sourced from configuration as defined in @.cursor/rules/global-config.mdc
Fetch configuration via config.FromContext(ctx); do not use global singletons
Promote tunable values (timeouts, deadlines, polling intervals, retry/backoff counts and factors, concurrency limits, queue sizes, buffer/payload limits, behavior thresholds) to configuration

In runtime code, properly inherit context; never use context.Background() in code paths

In runtime code paths, inherit context properly; never use context.Background()

In runtime code paths, never use context.Background(); properly inherit context

In runtime code, properly inherit context; never use context.Background()

Files:

  • engine/workflow/router/stream.go
  • engine/task/router/stream.go
  • engine/agent/router/stream.go
  • engine/infra/server/dependencies.go
  • docs/docs.go
  • engine/task/exec/runner.go
  • pkg/config/loader.go
  • pkg/config/config.go
engine/{agent,task,task2,tool,workflow,runtime,llm,memory,memorycfg,knowledge,model,mcp,webhook,attachment,resources,auth,autoload,project,schema,worker}/**/*.go

📄 CodeRabbit inference engine (.cursor/rules/architecture.mdc)

engine/{agent,task,task2,tool,workflow,runtime,llm,memory,memorycfg,knowledge,model,mcp,webhook,attachment,resources,auth,autoload,project,schema,worker}/**/*.go: Application Layer (engine/): implement domain-specific business logic and ports; organize by domain with uc/ and router/ subpackages
Port interfaces (e.g., repositories, external services) are defined in Application Layer packages where they are used
Application layer depends inward: Application → Domain; avoid depending on infrastructure

Files:

  • engine/workflow/router/stream.go
  • engine/task/router/stream.go
  • engine/agent/router/stream.go
  • engine/task/exec/runner.go
engine/*/router/**/*.go

📄 CodeRabbit inference engine (.cursor/rules/architecture.mdc)

Routers contain HTTP handling only (transport mapping, DTOs); no business logic

Files:

  • engine/workflow/router/stream.go
  • engine/task/router/stream.go
  • engine/agent/router/stream.go
{engine,pkg,cli}/**/*.go

📄 CodeRabbit inference engine (.cursor/rules/architecture.mdc)

Context as the first parameter for I/O or long-running operations; always propagate and handle cancellation

Files:

  • engine/workflow/router/stream.go
  • engine/task/router/stream.go
  • engine/agent/router/stream.go
  • engine/infra/server/dependencies.go
  • engine/task/exec/runner.go
  • pkg/config/loader.go
  • pkg/config/config.go
engine/infra/**/*.go

📄 CodeRabbit inference engine (.cursor/rules/architecture.mdc)

engine/infra/**/*.go: Infrastructure Layer (engine/infra): implement adapters for DB, cache, HTTP, storage, monitoring; must implement Application Layer interfaces
Adapter implementations belong in Infrastructure Layer and must implement Application Layer interfaces (no business logic leakage)
Infrastructure depends inward: Infrastructure → Application → Domain; avoid imports from cli and cross-infra coupling

Files:

  • engine/infra/server/dependencies.go
docs/**/*.go

📄 CodeRabbit inference engine (docs/.cursor/rules/review-checklist.mdc)

docs/**/*.go: Code must be formatted with go fmt
All linter warnings must be addressed
Error handling must follow project patterns
Security considerations must be addressed (e.g., no exposed secrets or unvalidated inputs)
Errors must be handled appropriately and with context
Interfaces must be used appropriately to define behavior
Code must pass all linter checks
Code must be secure and performant
Dependencies must be injected properly
Context must be propagated correctly
Hardcoded values that should be configurable must be avoided
Missing context propagation in functions that make external calls must be addressed
Performance issues like unnecessary allocations or inefficient algorithms must be avoided

docs/**/*.go: Use section comments with dashes for visual separation in Go code, formatted as:
// -----------------------------------------------------------------------------
// Section Name
// -----------------------------------------------------------------------------

Files:

  • docs/docs.go
pkg/config/loader.go

📄 CodeRabbit inference engine (.cursor/rules/global-config.mdc)

pkg/config/loader.go: Implement cross-field validation in validateCustom when struct tag validation is insufficient
Extend validateCustom for cross-field constraints in new categories when struct tags are insufficient

Files:

  • pkg/config/loader.go
pkg/**/*.go

📄 CodeRabbit inference engine (.cursor/rules/architecture.mdc)

Shared Packages (pkg): provide framework-level utilities (config, logging, templates, schema generation); must not contain business logic

Files:

  • pkg/config/loader.go
  • pkg/config/config.go
pkg/config/**/*.go

📄 CodeRabbit inference engine (.cursor/rules/architecture.mdc)

Global configuration resides in pkg/config; expose retrieval via context (config.FromContext) and provide defaults; avoid global singletons

Files:

  • pkg/config/loader.go
  • pkg/config/config.go
pkg/config/config.go

📄 CodeRabbit inference engine (.cursor/rules/global-config.mdc)

pkg/config/config.go: Add the new field to the typed config struct with tags: koanf/json/yaml/mapstructure; include env tag when applicable; add validate tag if needed; use SensitiveString or sensitive:"true" for secrets
Map from registry to typed struct in build

Config using getString/getInt/getBool/getDuration/getInt64/getStringSlice
For secrets, prefer SensitiveString type or sensitive:"true" tag to enable automatic JSON redaction
When creating a new category, define type
Config struct with full tagging and validation
Add the new section to the root Config with koanf/json/yaml/mapstructure tags
Implement build
Config(registry *definition.Registry) to map defaults from the registry to the typed struct
Always include koanf, json, yaml, and mapstructure tags on config struct fields; include env when applicable

Files:

  • pkg/config/config.go
{pkg/config/config.go,pkg/config/definition/schema.go}

📄 CodeRabbit inference engine (.cursor/rules/global-config.mdc)

Environment variable names must be UPPER_SNAKE_CASE with domain prefixes (e.g., SERVER_, DB_, RUNTIME_, CLI uses COMPOZY_)

Files:

  • pkg/config/config.go
🧬 Code graph analysis (3)
engine/infra/server/dependencies.go (5)
pkg/config/resolver.go (2)
  • ModeMemory (7-7)
  • ModePersistent (8-8)
engine/infra/server/server.go (1)
  • Server (34-64)
engine/worker/embedded/server.go (1)
  • Server (30-38)
pkg/config/config.go (1)
  • Config (58-148)
engine/worker/embedded/config.go (1)
  • Config (37-37)
pkg/config/loader.go (3)
pkg/config/config.go (2)
  • Config (58-148)
  • EmbeddedTemporalConfig (592-624)
engine/worker/embedded/config.go (1)
  • Config (37-37)
pkg/config/resolver.go (4)
  • ModeMemory (7-7)
  • ModePersistent (8-8)
  • ModeDistributed (9-9)
  • ModeRemoteTemporal (11-11)
pkg/config/config.go (1)
pkg/config/resolver.go (2)
  • ModeMemory (7-7)
  • ModePersistent (8-8)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: test
  • GitHub Check: Test Coverage
  • GitHub Check: Container Security Scan
  • GitHub Check: Analyze (go)
  • GitHub Check: Security Scan (gosec)
🔇 Additional comments (5)
engine/task/exec/runner.go (2)

39-39: LGTM: Store field properly integrated.

The store field is correctly added to the struct, initialized in the constructor (line 65), and used appropriately in loadTaskConfig (line 182) and hydrateAgentConfig (line 208).


95-107: LGTM: Clean dependency validation.

The validateRunner() method follows SRP and provides clear, specific error messages for each missing dependency. The early-return pattern keeps the logic flat and readable.

docs/docs.go (1)

1870-1870: docs/docs.go is correctly regenerated from updated source annotations.

Verification confirms that all changes in docs/docs.go reflect properly updated source Swagger annotations. The SSE endpoint descriptions and 503 error messages (including "Worker unavailable", "Pub/Sub provider unavailable", and "Workflow query client unavailable") originate from @description and @failure annotations in the corresponding source handlers:

  • engine/agent/router/stream.go: streamAgentExecution() handler includes routes.Base() context and "Pub/Sub provider unavailable" 503 error
  • engine/task/router/stream.go: streamTaskExecution() handler includes routes.Base() context and "Pubsub provider unavailable" 503 error
  • Additional 503 error descriptions found in engine/workflow/router/execute.go, execs.go, events.go, and stream.go

All 15 changes in docs/docs.go correctly represent the regenerated Swagger documentation from these updated source annotations.

engine/agent/router/stream.go (1)

119-119: LGTM!

The updated error message is more specific and accurately reflects the unavailable dependency. The "Pub/Sub" terminology is clear and professional.

engine/workflow/router/stream.go (1)

168-168: LGTM!

The updated error message correctly identifies the workflow-specific dependency (query client) as opposed to the pub/sub provider used in task and agent streaming endpoints. This provides clearer information to API consumers.

Comment on lines +441 to +454
case config.ModePersistent:
if dbFile == "" || dbFile == sqliteMemoryDSN {
fromValue := originalDBFile
if fromValue == "" {
fromValue = "(empty)"
}
log.Info(
"Overriding Temporal database file for persistent mode",
"mode", mode,
"from", fromValue,
"to", persistentDBPath,
)
dbFile = persistentDBPath
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Ensure persistent mode overrides all in-memory Temporal DSNs

file::memory:?cache=shared and similar URIs are still in-memory SQLite. In persistent mode we must force a file-backed path, otherwise Temporal keeps running ephemerally and state disappears on restart. Right now we only override when the value is exactly :memory:. Please treat the entire file::memory: family as in-memory (you already added sqliteMemoryFilePrefix for this) so persistent mode can’t silently lose data.

@@
-	dbFile := strings.TrimSpace(embeddedTemporal.DatabaseFile)
+	dbFile := strings.TrimSpace(embeddedTemporal.DatabaseFile)
+	dbLower := strings.ToLower(dbFile)
@@
-	case config.ModePersistent:
-		if dbFile == "" || dbFile == sqliteMemoryDSN {
+	case config.ModePersistent:
+		if dbFile == "" || dbLower == sqliteMemoryDSN || strings.HasPrefix(dbLower, sqliteMemoryFilePrefix) {
 			fromValue := originalDBFile
 			if fromValue == "" {
 				fromValue = "(empty)"
 			}

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In engine/infra/server/dependencies.go around lines 441 to 454, the
persistent-mode override only checks for an exact in-memory DSN but misses the
URI family (e.g. file::memory:?cache=shared); update the condition to treat any
DB file that equals sqliteMemoryDSN or has the sqliteMemoryFilePrefix prefix as
in-memory and therefore override it with persistentDBPath; use the existing
sqliteMemoryFilePrefix constant (and keep originalDBFile logging) so persistent
mode always forces a file-backed path.

Comment on lines +111 to 116
if ctx == nil {
return nil, fmt.Errorf("context is required")
}
if err := r.validateRunner(); err != nil {
return nil, err
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Suggest consistent error handling for context validation.

The context nil check uses fmt.Errorf("context is required") (also on line 157), while dependency validation uses predefined error constants (ErrStateRequired, etc.). For consistency with the existing error constants pattern (lines 27-32), consider adding ErrContextRequired to the error constant block and using it in both validation locations.

Apply this diff to add the constant at the top of the file:

 var (
 	ErrTaskIDRequired        = errors.New("task id is required")
 	ErrStateRequired         = errors.New("application state is required")
 	ErrRepositoryRequired    = errors.New("task repository is required")
 	ErrResourceStoreRequired = errors.New("resource store is required")
 	ErrProjectNameRequired   = errors.New("project name is required")
 	ErrNegativeTimeout       = errors.New("timeout must be non-negative")
+	ErrContextRequired       = errors.New("context is required")
 )

Then update the validation checks:

 func (r *Runner) Prepare(ctx context.Context, req ExecuteRequest) (*PreparedExecution, error) {
 	if ctx == nil {
-		return nil, fmt.Errorf("context is required")
+		return nil, ErrContextRequired
 	}
 func (r *Runner) ExecutePrepared(ctx context.Context, prepared *PreparedExecution) (*ExecuteResult, error) {
 	if ctx == nil {
-		return nil, fmt.Errorf("context is required")
+		return nil, ErrContextRequired
 	}

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In engine/task/exec/runner.go around lines 111-116 (and also update at line
157), the nil context checks use fmt.Errorf("context is required") while other
validations use predefined error constants; add a new error constant
ErrContextRequired to the file's error constant block near lines 27-32, then
replace the fmt.Errorf(...) occurrences at the two context checks with the new
ErrContextRequired constant so context validation follows the same
error-constant pattern as the other validations.

// @Failure 400 {object} router.Response{error=router.ErrorInfo} "Invalid request"
// @Failure 404 {object} router.Response{error=router.ErrorInfo} "Execution not found"
// @Failure 503 {object} router.Response{error=router.ErrorInfo} "Streaming infrastructure unavailable"
// @Failure 503 {object} router.Response{error=router.ErrorInfo} "Pubsub provider unavailable"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Inconsistent terminology with agent router.

The error message uses "Pubsub provider unavailable", while Line 119 in engine/agent/router/stream.go uses "Pub/Sub provider unavailable" (with capital P and slash). For consistency and clarity across API documentation, standardize the terminology.

Apply this diff to align with the agent router terminology:

-//	@Failure		503				{object}	router.Response{error=router.ErrorInfo}			"Pubsub provider unavailable"
+//	@Failure		503				{object}	router.Response{error=router.ErrorInfo}			"Pub/Sub provider unavailable"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// @Failure 503 {object} router.Response{error=router.ErrorInfo} "Pubsub provider unavailable"
// @Failure 503 {object} router.Response{error=router.ErrorInfo} "Pub/Sub provider unavailable"
🤖 Prompt for AI Agents
In engine/task/router/stream.go around line 107, the Swagger failure comment
reads "Pubsub provider unavailable" which is inconsistent with
engine/agent/router/stream.go (line 119) that uses "Pub/Sub provider
unavailable"; update the comment text to "Pub/Sub provider unavailable" (capital
P and slash) so the API docs use identical terminology across both routers.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant