بنقرة واحدة
ark-controller-development
// Guidance for developing the Ark Kubernetes operator. Use when modifying Go types, CRDs, controllers, or webhooks. Helps with CRD generation and Helm chart sync issues.
// Guidance for developing the Ark Kubernetes operator. Use when modifying Go types, CRDs, controllers, or webhooks. Helps with CRD generation and Helm chart sync issues.
Produce a themed Slack post announcing Ark releases. Pulls from BOTH the Ark core repo (mckinsey/agents-at-scale-ark) and the Marketplace repo (mckinsey/agents-at-scale-marketplace), validates docs links, groups features by theme with relevant emoji, and ends with a "Coming next" section sourced from the current sprint on the ARK project board. Invoke when the user asks for a "release announcement", "slack post", "what's new since vX", "changelog for
Structured workflow for drafting NEW GitHub issues with codebase research, duplicate detection, task breakdowns, and testing approach. Always asks clarifying questions and shows the draft for approval before creating. For searching, listing, viewing, or updating existing issues, use the "issues" skill instead.
Run and write Ark Chainsaw tests with mock-llm. Use for running tests, debugging failures, or creating new e2e tests.
Consolidate open Dependabot PRs into a single integration branch. Use when the user asks to "consolidate dependabot", "merge dependabot PRs", "batch dependency updates", or mentions dependabot PR management.
Set up and install the Ark platform in a Kubernetes cluster. Supports default mode (existing cluster) and isolated e2e testing mode (dedicated Kind cluster). Use when the user wants to install, deploy, test, or configure Ark.
CVE research and security patch workflow for Ark. Provides CVE API integration, mitigation strategies, and security-focused PR templates. Works with research, analysis, and setup skills for comprehensive vulnerability fixing.
| name | ark-controller-development |
| description | Guidance for developing the Ark Kubernetes operator. Use when modifying Go types, CRDs, controllers, or webhooks. Helps with CRD generation and Helm chart sync issues. |
Guidance for developing the Ark Kubernetes operator in ark/.
api/v1alpha1/*_types.go)api/v1alpha1/*_types.go # Go types with markers
↓
make manifests # Generates CRDs and syncs to Helm chart
↓
config/crd/bases/*.yaml # Source CRDs (auto-generated)
dist/chart/templates/crd/ # Helm chart CRDs (auto-synced)
make manifests automatically syncs source CRDs to the Helm chart while preserving templated headers.
When make build fails with CRD validation errors:
cd ark
make manifests
make build
| Directory | Purpose |
|---|---|
api/v1alpha1/ | Go type definitions |
config/crd/bases/ | Auto-generated source CRDs |
dist/chart/templates/crd/ | Helm chart CRDs (auto-synced) |
internal/controller/ | Reconciliation logic |
internal/webhook/ | Admission webhooks |
internal/genai/ | AI/ML execution logic |
Go type comments become CRD field descriptions:
cd ark
make manifests
make build
make lint-fix # Format and auto-fix what the linter can fix
make lint # Fail fast on issues CI will reject — MANDATORY
make build # Build and validate
make test # Run unit + envtest suites
Run the chainsaw e2e suite against a live cluster — unit + envtest don't exercise the full apply → reconcile → status loop. Prefer the deterministic mock-llm suite; only run the LLM-backed tests when the change specifically touches that path (saves cost + avoids flakes from real LLM providers).
# Deterministic suite (default)
(cd tests && chainsaw test --selector '!llm')
# LLM suite — only when your change needs it
(cd tests && chainsaw test --selector 'llm')
See the chainsaw skill for patterns and antipatterns (e.g. prefer
chainsaw assert over shell grep; prefer wait over polling).
make lint runs the same golangci-lint rules CI enforces. Running it
locally before pushing is non-negotiable — red PR checks cost more than
the minute the lint takes.
Before writing a parser, struct, helper, retry loop, URL builder, or any utility, check whether it already exists in:
go.mod (controller-runtime, apimachinery, the SDK for whatever spec you're implementing, golang.org/x/...).Hand-rolled code drifts, duplicates tests, and becomes maintenance burden. A short adapter delegating to a library is almost always better than a reimplementation.
Heuristic: if the thing you're writing mirrors an existing spec, file
format, header syntax, or common infra pattern, someone has already
written it. Search first: go doc <import-path>, ls $(go env GOMODCACHE)/<dep>.
Re-export library types via alias (type X = lib.X) rather than
defining a parallel struct with the same fields.
Started this project by hand-rolling a WWW-Authenticate parser, RFC 9728
struct, RFC 8414 struct, and HTTP fetchers — ~150 LOC. The go-sdk
already shipped them in oauthex:
// Bad — 40-line parser, partial struct, duplicated HTTP wrapper.
func parseHeader(h string) (string, bool) { /* ... */ }
type Metadata struct { /* partial mirror of RFC */ }
func fetch(ctx, url) (*Metadata, error) { /* 30 lines */ }
// Good — thin adapter, full spec support, ~10 LOC.
import "github.com/modelcontextprotocol/go-sdk/oauthex"
type Metadata = oauthex.ProtectedResourceMetadata
func Fetch(ctx context.Context, metaURL, resourceURL string, timeout time.Duration) (*Metadata, error) {
return oauthex.GetProtectedResourceMetadata(ctx, metaURL, resourceURL, &http.Client{Timeout: timeout})
}
Same principle applies to retry/backoff (k8s.io/apimachinery/pkg/util/wait),
JSON patch (strategicpatch), condition updates
(meta.SetStatusCondition), HTTP clients, workqueues — whatever you're
touching, check the existing deps first.
Never inline numeric durations, retry counts, or buffer sizes. Priority:
spec.timeout, spec.pollInterval, spec.retries, use it. One
operator knob should govern all related code paths in the same
reconcile.const testTimeout = 5 * time.Second) —
never inline literals in tests.// Bad — parallel constant invented out of thin air.
const discoveryTimeout = 10 * time.Second
client := &http.Client{Timeout: discoveryTimeout}
// Good — plumb the MCPServer's spec.timeout; single source of truth.
func Fetch(ctx, url string, timeout time.Duration) ...
timeout := parseTimeout(mcpServer.Spec.Timeout)
Every code change ships with tests. A PR touching ark/internal/ with
no _test.go is incomplete. Applies to controller branches, webhooks,
helpers — not just public APIs.
| Change | Where | Framework |
|---|---|---|
Helper / parser in internal/<pkg>/ | <file>_test.go | stdlib testing, table-driven |
| Controller branch | internal/controller/<scenario>_test.go | Ginkgo + envtest |
| Webhook rule | internal/webhook/v1/<resource>_webhook_test.go | Ginkgo |
| HTTP logic | httptest.NewServer in same package | stdlib testing |
Required coverage for a controller branch:
lastTransitionTime.Before saying "done":
make manifests clean (if types changed)make lint clean — same rules CI enforcesmake build greenmake test green — paste or reference outputchainsaw test --selector '!llm') green; LLM suite only if change requires it_test.go exists for every new function / branch