---
title: "Kubernetes support — implementation plan"
description: "- **Feature:** kubernetes-support - **Design:** [design.md](design.md) - **Tasks:** [tasks.md](tasks.md) - **Status:** implementation-plan - **Branch:** `k8s_support`"
type: skill
canonical_url: https://claudary.paisolsolutions.com/skills/implementation-7
source: "Claudary"
difficulty: intermediate
author: "Claude Code Knowledge Pack"
date: 2026-07-10T11:25:20.399Z
license: CC-BY-4.0
attribution: "Kubernetes support — implementation plan — Claudary (https://claudary.paisolsolutions.com/skills/implementation-7)"
---

# Kubernetes support — implementation plan
- **Feature:** kubernetes-support - **Design:** [design.md](design.md) - **Tasks:** [tasks.md](tasks.md) - **Status:** implementation-plan - **Branch:** `k8s_support`

## Overview

# Kubernetes support — implementation plan

- **Feature:** kubernetes-support
- **Design:** [design.md](design.md)
- **Tasks:** [tasks.md](tasks.md)
- **Status:** implementation-plan
- **Branch:** `k8s_support`

This document is a step-by-step guide for implementing the design. Each step is paired with an explicit verification. Tasks in [tasks.md](tasks.md) reference the corresponding steps here.

## Conventions

- All file paths in this document are relative to the repository root unless noted otherwise.
- Each step's **verify** clause specifies how the implementer confirms the step succeeded. Steps without a verification are not considered complete.
- Commits are atomic per task in [tasks.md](tasks.md); a task may span multiple steps here, but the steps collectively map to one self-contained commit.
- The order of steps within a phase is significant; dependencies are stated explicitly where a later step requires the output of an earlier one.

## Prerequisites

Before starting P0:

1. The three ADRs ([0001](../../adr/0001-profile-detection-model.md), [0002](../../adr/0002-profile-content-organization.md), [0003](../../adr/0003-plugin-root-referenced-content.md)) have been authored in `docs/adr/`.
2. `docs/wip/kubernetes-support/` exists with this file, `design.md`, and `tasks.md`.
3. The branch `k8s_support` is checked out (confirm with `git branch --show-current`).
4. The plugin-structure test currently passes on the branch (confirm with `bash test/test-plugin-structure.sh` — captures the pre-P0 baseline).

## Phase 0 — Profile-first refactor

**Goal.** Introduce `klaude-plugin/profiles/` as a top-level directory; migrate programming-language checklist content from `klaude-plugin/skills/review-code/reference/<lang>/` to `klaude-plugin/profiles/<lang>/review-code/`; author the shared detection procedure and the six consumer symlinks; restructure the `review-code` workflow to be index-driven; update the plugin-structure test, `CLAUDE.md`, and `README.md`. Behavior must remain equivalent to pre-P0 when `review-code` is invoked on diffs affecting the existing programming-language profiles.

### Step 0.1 — Create the `profiles/` top level and migrate programming-language checklists

For each language in (`go`, `python`, `java`, `js_ts`, `kotlin`):

1. Create directory `klaude-plugin/profiles/<lang>/review-code/`.
2. Move the existing files from `klaude-plugin/skills/review-code/reference/<lang>/` to `klaude-plugin/profiles/<lang>/review-code/` using `git mv` (preserves history).
3. Author `klaude-plugin/profiles/<lang>/DETECTION.md` using the mandatory three-section schema (see [design.md §Detection mechanics](design.md#detection-mechanics)): `## Path signals` (empty for programming-language profiles; file-extension detection does not involve path heuristics), `## Filename signals` (empty — language detection is extension-based, not filename-based), `## Content signals` (the file-extension rule: "any file whose extension matches `.go` / `.py` / etc."). The three sections must be present even when empty, so the shared procedure iterates predictably.
4. Author `klaude-plugin/profiles/<lang>/overview.md` — a one-page summary: what the profile covers (the programming language), when it activates, and "Looking up dependencies" targets (context7, language-specific references).
5. Author `klaude-plugin/profiles/<lang>/review-code/index.md` — lists the four migrated files (`security-checklist.md`, `solid-checklist.md`, `code-quality-checklist.md`, `removal-plan.md`) in the "Always load" section with one-line descriptions. No conditional entries for programming-language profiles.
6. Remove the now-empty `klaude-plugin/skills/review-code/reference/<lang>/` directory.

After iterating through all five languages, remove `klaude-plugin/skills/review-code/reference/` itself (now empty).

**Audit downstream migration impact.** Check `.github/scripts/template-sync.sh` for a `run_plugin_migration` function with a `dirs_to_remove` array (or equivalent mechanism). Determine whether the removal of `klaude-plugin/skills/review-code/reference/` requires an entry there to clean up downstream projects that have migrated from an older template version. Document the decision (add an entry OR document that no entry is needed — CLAUDE.md's "don't touch historical entries" directive covers pre-v0.5.0 historical paths, not new migrations introduced by this feature). If an entry is added, follow the existing entry format and date the addition.

**Verify.**
- `ls klaude-plugin/profiles/` shows exactly `go`, `java`, `js_ts`, `kotlin`, `python` (plus, after P1, `k8s`).
- `ls klaude-plugin/skills/review-code/reference/` returns "No such file or directory".
- For each language: `test -f klaude-plugin/profiles/<lang>/{DETECTION.md,overview.md,review-code/index.md}` succeeds.
- For each language: the profile's `DETECTION.md` contains the three required sections (`## Path signals`, `## Filename signals`, `## Content signals`) — any may be empty but all three headings must be present.
- `git log --follow klaude-plugin/profiles/go/review-code/security-checklist.md` shows history continuous with the old path.
- Template-sync audit decision documented in the PR description or as a comment in `template-sync.sh`.

### Step 0.2 — Author the shared profile-detection procedure

Create `klaude-plugin/skills/_shared/profile-detection.md` with the following mandatory sections:

1. **Purpose.** Single source of truth for "compute the set of active profiles for the current context." Used by six consuming skills; the shared file exists to prevent interpretation drift.
2. **Per-consumer input model.** Enumerate what each consuming skill passes as detection input:
   - `review-code` → git diff (staged or explicit range, scoped to the diff's touched files).
   - `review-spec` → git diff when invoked standalone; the feature directory's full file list when invoked by `implement`.
   - `test` → git diff (mid-feature) or full feature-directory file list (post-implementation).
   - `implement` → the current sub-task's target file list, optionally augmented by the diff accumulated so far.
   - `design` → user-declared signal OR keyword inference from the idea prose. Detection in the design phase is not file-based. The file must spell out the interaction: "check idea prose against the high-precision auto-trigger set (`Kubernetes`, `K8s`, `Helm chart`, `kubectl`, `kustomize`, `manifest.yaml`, `Deployment resource`, `StatefulSet`, `DaemonSet`, `CronJob`); if any match, ask the user to confirm activation. If no auto-trigger matches but the idea is ambiguous — names infrastructure, deployment, runtime, or platform concerns without naming a specific technology, or includes tokens like `cluster`/`namespace`/`pod` that collide with non-K8s meanings — ask explicitly." Rationale: the narrow auto-trigger set avoids noisy false positives from overloaded tokens.
   - `document` → the feature directory's current file list; diff is optional.
3. **Detection algorithm.** Iterate `klaude-plugin/profiles/*/DETECTION.md`. For each profile, evaluate signals in cost order (path → filename → content). Apply authority rule: filename or content signal matches activate the profile; path signal alone does not activate. Bounded content inspection: ~16 KB per file; multi-document YAML inspected per `---`-separated block. Every profile's `DETECTION.md` uses the three-section schema (`## Path signals` / `## Filename signals` / `## Content signals`); the shared procedure applies the same algorithm against each profile's declared values.
4. **Unset-variable check.** Before returning results, verify `${CLAUDE_PLUGIN_ROOT}` is set. If unset: emit a loud error message naming the variable and pointing at CLAUDE.md's Profile Conventions section; return the empty-set result so consumers fall back to generic guidance rather than panicking. (Per [ADR 0003 §Decision](../../adr/0003-plugin-root-referenced-content.md), the brace form is mandatory — `$CLAUDE_PLUGIN_ROOT` without braces is NOT substituted by the Claude Code harness and will never be used here.)

**Authoring caveat for the shared file itself.** `klaude-plugin/skills/_shared/profile-detection.md` lives INSIDE the plugin tree and is therefore subject to `${CLAUDE_PLUGIN_ROOT}` substitution when an agent reads it. When the file needs to describe the variable BY NAME (e.g., "check that `$CLAUDE_PLUGIN_ROOT` is set"), use the bare form `$CLAUDE_PLUGIN_ROOT` (without braces) — the bare form is not substituted (verified 2026-04-18, ADR 0003 §Verification). When the file uses the variable as a PATH that must resolve at runtime (e.g., `${CLAUDE_PLUGIN_ROOT}/profiles/*/DETECTION.md`), use the brace form — that is the intended substitution. Mixing the two conventions in the same file is normal and correct.
5. **Output shape.** A list of records, one per matched profile: `{profile: <name>, triggered_by: [<signal descriptions>], files: [<paths>]}`. `triggered_by` names the signal type that fired (e.g., `"filename: Chart.yaml"`, `"content: apiVersion+kind in block 2"`).

**Verify.** `test -f klaude-plugin/skills/_shared/profile-detection.md`. The file contains all five sections by heading. File size is ~120–200 lines (a few pages; not a brief summary). Content is readable by a skilled contributor unfamiliar with the plugin — pass it to a colleague for a sanity read.

### Step 0.3 — Create the six consumer symlinks

Create the following symlinks (each is `shared-profile-detection.md` pointing at `../_shared/profile-detection.md`):

- `klaude-plugin/skills/review-code/shared-profile-detection.md`
- `klaude-plugin/skills/review-spec/shared-profile-detection.md`
- `klaude-plugin/skills/design/shared-profile-detection.md`
- `klaude-plugin/skills/implement/shared-profile-detection.md`
- `klaude-plugin/skills/test/shared-profile-detection.md`
- `klaude-plugin/skills/document/shared-profile-detection.md`

**Verify.**
- For each symlink path P: `test -L P` succeeds; `readlink P` returns `../_shared/profile-detection.md`; `realpath P` resolves to the shared file.

### Step 0.4 — Restructure the `review-code` workflow

Update the following files to consume `shared-profile-detection.md` and the index-driven loading pattern. Each file needs **specific literal-string replacements**, not just behavioral intent — the old prose hardcodes `reference/<lang>/` paths in multiple places, and the grep verification below catches missed replacements.

- `klaude-plugin/skills/review-code/SKILL.md` — prose gains a sentence linking `[shared-profile-detection.md](shared-profile-detection.md)` (per CLAUDE.md convention: consumers reference the per-skill symlink, not the shared source). No change to the description frontmatter.
- `klaude-plugin/skills/review-code/review-process.md`:
  - "Step 2: Detect primary language" renames to "Step 2: Detect active profiles" and delegates to the shared procedure.
  - Former Steps 3–6 (SOLID / Removal / Security / Quality) collapse into:
    - "Step 3: Load profile review indexes." For each active profile, resolve `${CLAUDE_PLUGIN_ROOT}/profiles/<name>/review-code/index.md`; collect always-load entries and conditional entries whose stated triggers match the diff.
    - "Step 4: Apply checklists." Iterate the resolved checklists; each checklist's findings are emitted with `(profile, checklist)` as the grouping key.
  - Subsequent steps (self-check, indexing, output formatting) are renumbered but otherwise unchanged.
  - Replace every literal occurrence of `reference/<lang>/` and `reference/{lang}/` (any variant) with the `${CLAUDE_PLUGIN_ROOT}/profiles/...` equivalent or a description of the index-driven loading step.
- `klaude-plugin/skills/review-code/review-isolated.md` — the same restructure pattern, adapted for the isolated sub-agent variant.
  - **Literal path string to replace:** the sub-agent prompt template in Step 2 currently injects `klaude-plugin/skills/review-code/reference/{language_key}/` into the spawned agent's prompt. This literal string must be replaced with the list of resolved checklists (produced in Step 1 when preparing the scope block). The sub-agent receives the list, not a path.
  - Replace every other literal occurrence of `reference/<lang>/` in the file.
- `klaude-plugin/agents/code-reviewer.md` — the prompt updates to iterate the `(profile, checklist)` list it is given, rather than iterating fixed category names.
  - **Literal path string to replace:** the agent's current Step 2 says "Load the corresponding reference checklists from `klaude-plugin/skills/review-code/reference/{lang}/`" with the full extension table duplicated. Rewrite to: "Apply the checklists provided in the input payload; for each `(profile, checklist)` record, read the checklist content from `${CLAUDE_PLUGIN_ROOT}/profiles/<profile>/review-code/<checklist>` and apply it to the diff." Remove the extension table (detection is no longer the agent's responsibility; the calling skill has already produced the list).

**Verify.**
- Grep check (expanded scope to include `agents/`): `grep -rn 'reference/' klaude-plugin/skills/review-code/ klaude-plugin/agents/code-reviewer.md` returns no lines. If any remain, replacement was incomplete.
- Grep check: `grep -rn '${CLAUDE_PLUGIN_ROOT}/profiles/' klaude-plugin/skills/review-code/` returns matches at the relevant points (Step 3 of review-process.md, equivalent in review-isolated.md).
- Manual dry-run: invoke `/kk:review-code` on a Go-only diff (e.g., a recent commit touching only `.go` files). The output identifies the `go` profile as active and loads the four checklists now at `profiles/go/review-code/`. Findings coverage and categories match pre-P0 output qualitatively.
- `klaude-plugin/agents/code-reviewer.md` parses cleanly (front-matter valid, instructions coherent on a manual read).

### Step 0.5 — Update the plugin-structure test

Modify `test/test-plugin-structure.sh`:

- Add `EXPECTED_PROFILES=("go" "java" "js_ts" "kotlin" "python")` (`k8s` will be added in alphabetical position in Step 1.3 of P1, after k8s content files exist; the array is alphabetised and the structure test treats it as a set).
- **Per-profile assertions (presence-conditional).** Assertions are predicated on what the profile declares; they do NOT require every profile to populate every phase subdirectory:
  - Directory `klaude-plugin/profiles/<name>/` exists (required for every profile in `EXPECTED_PROFILES`).
  - File `klaude-plugin/profiles/<name>/DETECTION.md` exists (required).
  - `DETECTION.md` contains the three required section headings (`## Path signals`, `## Filename signals`, `## Content signals`). Any may be empty; all must be present. Use `grep -c '^## Path signals' ...` and similar to verify each header appears exactly once.
  - File `klaude-plugin/profiles/<name>/overview.md` exists (required).
  - For each phase subdirectory name in (`review-code`, `design`, `test`, `implement`, `document`, `review-spec`): IF `klaude-plugin/profiles/<

---

Source: [Claudary](https://claudary.paisolsolutions.com/skills/implementation-7) · https://claudary.paisolsolutions.com
