From b945436ec9a8cd68da6f6c675d83649111d27c65 Mon Sep 17 00:00:00 2001 From: Jon Langevin Date: Thu, 4 Jun 2026 20:52:08 -0400 Subject: [PATCH 01/12] docs: design for surfacing cigen info in wfctl MCP output Co-Authored-By: Claude Opus 4.8 (1M context) --- .../plans/2026-06-04-mcp-cigen-info-design.md | 86 +++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 docs/plans/2026-06-04-mcp-cigen-info-design.md diff --git a/docs/plans/2026-06-04-mcp-cigen-info-design.md b/docs/plans/2026-06-04-mcp-cigen-info-design.md new file mode 100644 index 00000000..93c220f5 --- /dev/null +++ b/docs/plans/2026-06-04-mcp-cigen-info-design.md @@ -0,0 +1,86 @@ +# Surface cigen information in wfctl's MCP output — design + +**Date:** 2026-06-04 +**Status:** Design (adversarial review pending) +**Repo:** `workflow` (the `mcp/` package + `docs/mcp-tools-reference.md`) +**Guidance:** `docs/AGENT_GUIDE.md` + `CLAUDE.md` (no `docs/design-guidance.md`). + +## 1. Problem + +The render path is already cigen-backed, but the MCP server's *information* about it is stale/missing, so an AI driving the MCP can't tell the config-derived CI surface exists or how it behaves: + +- **Instructions string** (`mcp/server.go`, `WithInstructions`): says generic "CI/CD generation". No `ci_plan`, no cigen, no config-derived framing. +- **`workflow://docs/overview` resource** (`mcp/docs.go`, `docsOverview` const): the "CI/CD & Git Integration" section lists only the legacy `wfctl generate github-actions`. Nothing on `wfctl ci plan` / `wfctl ci generate` or the config-derived nature. +- **`generate_github_actions` tool description** (`mcp/wfctl_tools.go`): "based on analysis" — doesn't name cigen, per-phase secret scoping, the migrations step, smoke, or plan-guard. The tool is a **hybrid**: CI (`files`/`ci_yaml`) is cigen-derived; `cd_yaml`/`release_yaml` are still legacy template (driven by the `registry`/`platforms` inputs). The description hides both facts. +- **`docs/mcp-tools-reference.md`** (human reference for the MCP tools): omits `ci_plan` and `generate_github_actions` entirely. + +Ground truth (verified @ `main` 905405954): `handleGenerateGithubActions` routes through `cigen.Analyze` + `cigen.RenderGitHubActions` (`mcp/wfctl_tools.go:416-421`); `cd_yaml`/`release_yaml` come from `mcpGenerateCDWorkflow(features, registry, platforms)` (legacy template). `ci_plan` already exists and is cigen-backed. `docs/WFCTL.md:2140+` already documents `ci generate`/cigen accurately (so the CLI docs are the wording reference — do not diverge). + +## 2. Goal + +MCP output (runtime Instructions + the `workflow://docs/overview` resource + the two tool descriptions) and `docs/mcp-tools-reference.md` accurately describe the cigen config-derived CI surface and the `generate_github_actions` hybrid. **Informational only:** no new tools, no handler/behavior change, no release. + +## 3. Non-goals + +- No new MCP tool (e.g. a `ci_generate`/from-plan render tool). The render path already exists (`generate_github_actions`); only the *information* is missing. (Logged as a possible future follow-up, not built here.) +- No change to any handler, the CIPlan shape, or the `registry`/`platforms` inputs. +- No edit to `docs/WFCTL.md` (already accurate) — reuse its wording for consistency. +- No GitLab/Jenkins/CircleCI behavior change. + +## 4. Architecture / changes (4 surfaces, 1 PR) + +1. **`mcp/server.go` `WithInstructions`** — insert a cigen sentence: the `ci_plan` tool analyzes a config into a config-derived CIPlan (deploy phases, secrets scoped per phase, a `wfctl migrations up` step, a health-check smoke job, a plan-guard); `generate_github_actions` renders it to GitHub Actions YAML; both derive CI from the app config, not fixed templates; mirrors the `wfctl ci plan` / `ci generate` commands. Change the trailing "CI/CD generation" list item to "config-derived CI/CD generation (ci plan / ci generate)". + +2. **`mcp/docs.go` `docsOverview`** — replace the single legacy CLI line in "CI/CD & Git Integration" with: a short "config-derived (cigen)" framing paragraph (per-phase secret scoping, `wfctl migrations up` step with `--format json`/`--env` when derivable, smoke job, plugin-install, plan-guard; GHA/GitLab config-derived, Jenkins/CircleCI template-based), the `wfctl ci plan` and `wfctl ci generate` commands (with the real flags from `docs/WFCTL.md`), a note that legacy `wfctl generate github-actions` now renders through cigen, and the MCP equivalents (`ci_plan` returns the CIPlan; `generate_github_actions` renders it). Keep the two `wfctl git …` lines under a "Git Integration" sub-heading. + +3. **`mcp/wfctl_tools.go`** — + - `generate_github_actions` description: render CI via the cigen engine — config-derived (`files`/`ci_yaml`): per-phase scoped secrets, a `wfctl migrations up` step when `ci.migrations` is set, a smoke job, plugin-install steps, a plan-guard that fails on replace/destroy; also returns the `plan` (CIPlan) and **legacy template-based** `cd_yaml`/`release_yaml` (these use the `registry`/`platforms` inputs); use `ci_plan` to inspect/edit the plan first, or pass `phase_config_yaml` for a two-phase pipeline. + - `ci_plan` description: minor — note secrets are scoped per phase (not just a union) and that `generate_github_actions` renders the plan in-process. + +4. **`docs/mcp-tools-reference.md`** — add a `ci_plan` entry and a `generate_github_actions` entry mirroring the file's existing per-tool format (heading + one-line purpose + an inputs table). Inputs from the tool defs: `ci_plan` (`yaml_content` req, `phase_config_yaml`, `wfctl_version`); `generate_github_actions` (`yaml_content` req, `registry`, `platforms`). + +## 5. Testing + +- `GOWORK=off go build ./...` + `GOWORK=off go test ./mcp/...` — the `docsOverview` const is compile-time; tool descriptions are plain strings. Confirms nothing that enumerates tools/asserts metadata breaks (no test currently pins these strings — verified). +- **Runtime / multi-component:** build the MCP binary and start the server (`wfctl mcp`), then assert the rendered Instructions and the `workflow://docs/overview` resource contain "cigen"/"ci plan" and that the `generate_github_actions` tool description names cigen. (Add a focused `mcp` package test that calls `NewServer(...)` and asserts the Instructions string + the `docsOverview` const + the two tool descriptions contain the cigen keywords — exercises the real server, not a mock.) +- `GOWORK=off golangci-lint run --new-from-rev=origin/main ./mcp/...`. +- Markdown: `docs/mcp-tools-reference.md` renders (no broken table). + +## Global Design Guidance + +Source: `docs/AGENT_GUIDE.md` + `CLAUDE.md`. + +| guidance | response | +|---|---| +| Update docs with behavior/CLI/config changes (CLAUDE.md) | This *is* a doc/metadata accuracy fix; updates the MCP runtime docs + `docs/mcp-tools-reference.md` | +| CI-gen changes touch `cigen/`, `cmd/wfctl/ci*.go`, `docs/WFCTL.md`, ci-generator (AGENT_GUIDE:48) | No CI-gen *behavior* change; only MCP-side information. `docs/WFCTL.md` already accurate (reused, not edited). No plugin impact (no contract change). | +| Keep committed examples under `example/` | N/A (no examples added) | + +## Security Review + +None. Static descriptive strings + a markdown doc. No auth/authz, no secrets (secret *names* already surfaced by cigen output; this only describes that behavior), no PII, no new trust boundary, no new input handling. + +## Infrastructure Impact + +None. No cloud resources, no migrations, no network exposure, no release. Compile-time string/const changes + one markdown file. + +## Multi-Component Validation + +Real boundary = MCP server ↔ AI client. Proof: construct the real `mcp.NewServer(...)` and assert the Instructions + `workflow://docs/overview` resource + tool descriptions carry the cigen keywords (the server's actual output an MCP client would receive). No mock. + +## Assumptions + +1. `generate_github_actions` CI output is cigen-derived; `cd_yaml`/`release_yaml` are legacy template using `registry`/`platforms`. *(Verified: `mcp/wfctl_tools.go:416-453`.)* +2. No test pins the Instructions / tool-description / `docsOverview` strings verbatim. *(Verified by grep; the new assertion test will use `Contains`, not equality.)* +3. `docs/WFCTL.md` already documents `ci plan`/`ci generate`/cigen accurately, so MCP wording can mirror it. *(Verified: `docs/WFCTL.md:178,2140+`.)* +4. `docs/mcp-tools-reference.md` has a stable per-tool format (heading + purpose + inputs table) to mirror. *(Verified: e.g. `template_validate_config` entry.)* + +## Rollback + +Not a runtime-affecting change class (no build/deploy/version-pin/startup/migration/plugin-loading change). Rollback = revert the PR; the MCP reverts to the prior (generic) strings. No release, no state, no migration. + +## Self-challenge — top doubts + +1. **Hybrid detail in a tool description may be too much.** Mitigation: keep it to one clause ("CI via cigen; `cd_yaml`/`release_yaml` are legacy template") — accurate without a paragraph. +2. **Wording could diverge from `docs/WFCTL.md`.** Mitigation: reuse WFCTL.md's cigen phrasing; don't re-invent. +3. **Ref-doc format drift.** Mitigation: copy the existing entry shape in `docs/mcp-tools-reference.md` exactly. From f6d46348127e5c86bf367b4080839e25568fd5d6 Mon Sep 17 00:00:00 2001 From: Jon Langevin Date: Thu, 4 Jun 2026 20:56:45 -0400 Subject: [PATCH 02/12] docs: revise mcp-cigen design per adversarial C1/I1/I2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - C1: all four CI platforms are config-derived from the CIPlan (not Jenkins/CircleCI=template); the only hybrid is within generate_github_actions (cigen CI vs legacy cd_yaml/release_yaml) - I1: add 5th surface — setup_guide.go CI/CD Setup Flow (cigen path + scaffold_ci-vs-cigen relationship) - I2: exact param names for ref-doc entries + correct the stale scaffold_ci entry; scope out scaffold_environment/infra Co-Authored-By: Claude Opus 4.8 (1M context) --- .../plans/2026-06-04-mcp-cigen-info-design.md | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/docs/plans/2026-06-04-mcp-cigen-info-design.md b/docs/plans/2026-06-04-mcp-cigen-info-design.md index 93c220f5..b67d5c51 100644 --- a/docs/plans/2026-06-04-mcp-cigen-info-design.md +++ b/docs/plans/2026-06-04-mcp-cigen-info-design.md @@ -12,9 +12,10 @@ The render path is already cigen-backed, but the MCP server's *information* abou - **Instructions string** (`mcp/server.go`, `WithInstructions`): says generic "CI/CD generation". No `ci_plan`, no cigen, no config-derived framing. - **`workflow://docs/overview` resource** (`mcp/docs.go`, `docsOverview` const): the "CI/CD & Git Integration" section lists only the legacy `wfctl generate github-actions`. Nothing on `wfctl ci plan` / `wfctl ci generate` or the config-derived nature. - **`generate_github_actions` tool description** (`mcp/wfctl_tools.go`): "based on analysis" — doesn't name cigen, per-phase secret scoping, the migrations step, smoke, or plan-guard. The tool is a **hybrid**: CI (`files`/`ci_yaml`) is cigen-derived; `cd_yaml`/`release_yaml` are still legacy template (driven by the `registry`/`platforms` inputs). The description hides both facts. -- **`docs/mcp-tools-reference.md`** (human reference for the MCP tools): omits `ci_plan` and `generate_github_actions` entirely. +- **`docs/mcp-tools-reference.md`** (human reference for the MCP tools): omits `ci_plan` and `generate_github_actions` entirely. Its existing `scaffold_ci` entry is **stale** (lists a `provider` param incl `circleci`; the real tool takes `description` req + `yaml_content` opt — `mcp/scaffold_tools.go:20-28`). +- **`workflow://docs/setup-guide` resource** (`mcp/setup_guide.go`, "CI/CD Setup Flow" ~line 61): routes the AI through `scaffold_ci` → `generate_bootstrap` → `wfctl ci run` and **never mentions cigen / `ci plan` / `ci generate`**, so the server's own AI-onboarding decision tree steers *away* from the config-derived path. (These are genuinely distinct: `scaffold_ci` emits a `ci:` *section* in the app config and `generate_bootstrap` emits a thin file that calls `wfctl ci run`; cigen *renders* a full platform-native workflow from the config. Both are valid — the gap is that the relationship is never stated.) -Ground truth (verified @ `main` 905405954): `handleGenerateGithubActions` routes through `cigen.Analyze` + `cigen.RenderGitHubActions` (`mcp/wfctl_tools.go:416-421`); `cd_yaml`/`release_yaml` come from `mcpGenerateCDWorkflow(features, registry, platforms)` (legacy template). `ci_plan` already exists and is cigen-backed. `docs/WFCTL.md:2140+` already documents `ci generate`/cigen accurately (so the CLI docs are the wording reference — do not diverge). +Ground truth (verified @ `main` 905405954): `handleGenerateGithubActions` routes through `cigen.Analyze` + `cigen.RenderGitHubActions` (`mcp/wfctl_tools.go:416-421`); `cd_yaml`/`release_yaml` come from `mcpGenerateCDWorkflow(features, registry, platforms)` (legacy template — this is the ONLY hybrid). `ci_plan` already exists and is cigen-backed. **All four platforms (`github_actions`, `gitlab_ci`, `jenkins`, `circleci`) are config-derived from the same CIPlan** (`docs/WFCTL.md:2142`; RenderJenkins/RenderCircleCI mirror GHA per workflow#810 / ADR 0044) — there is NO "GHA-only is smart, Jenkins/CircleCI are templates" split. `docs/WFCTL.md:2140+` documents `ci generate`/cigen accurately (CLI docs are the wording reference — do not diverge). ## 2. Goal @@ -27,22 +28,24 @@ MCP output (runtime Instructions + the `workflow://docs/overview` resource + the - No edit to `docs/WFCTL.md` (already accurate) — reuse its wording for consistency. - No GitLab/Jenkins/CircleCI behavior change. -## 4. Architecture / changes (4 surfaces, 1 PR) +## 4. Architecture / changes (5 surfaces, 1 PR) 1. **`mcp/server.go` `WithInstructions`** — insert a cigen sentence: the `ci_plan` tool analyzes a config into a config-derived CIPlan (deploy phases, secrets scoped per phase, a `wfctl migrations up` step, a health-check smoke job, a plan-guard); `generate_github_actions` renders it to GitHub Actions YAML; both derive CI from the app config, not fixed templates; mirrors the `wfctl ci plan` / `ci generate` commands. Change the trailing "CI/CD generation" list item to "config-derived CI/CD generation (ci plan / ci generate)". -2. **`mcp/docs.go` `docsOverview`** — replace the single legacy CLI line in "CI/CD & Git Integration" with: a short "config-derived (cigen)" framing paragraph (per-phase secret scoping, `wfctl migrations up` step with `--format json`/`--env` when derivable, smoke job, plugin-install, plan-guard; GHA/GitLab config-derived, Jenkins/CircleCI template-based), the `wfctl ci plan` and `wfctl ci generate` commands (with the real flags from `docs/WFCTL.md`), a note that legacy `wfctl generate github-actions` now renders through cigen, and the MCP equivalents (`ci_plan` returns the CIPlan; `generate_github_actions` renders it). Keep the two `wfctl git …` lines under a "Git Integration" sub-heading. +2. **`mcp/docs.go` `docsOverview`** — replace the single legacy CLI line in "CI/CD & Git Integration" with: a short "config-derived (cigen)" framing paragraph (per-phase secret scoping, `wfctl migrations up` step with `--format json`/`--env` when derivable, smoke job, plugin-install, plan-guard; **all four target platforms — `github_actions`, `gitlab_ci`, `jenkins`, `circleci` — are config-derived from the same CIPlan**, mirroring `docs/WFCTL.md:2142`), the `wfctl ci plan` and `wfctl ci generate` commands (with the real flags from `docs/WFCTL.md`), a note that legacy `wfctl generate github-actions` now renders through cigen, and the MCP equivalents (`ci_plan` returns the CIPlan; `generate_github_actions` renders it). Keep the two `wfctl git …` lines under a "Git Integration" sub-heading. 3. **`mcp/wfctl_tools.go`** — - `generate_github_actions` description: render CI via the cigen engine — config-derived (`files`/`ci_yaml`): per-phase scoped secrets, a `wfctl migrations up` step when `ci.migrations` is set, a smoke job, plugin-install steps, a plan-guard that fails on replace/destroy; also returns the `plan` (CIPlan) and **legacy template-based** `cd_yaml`/`release_yaml` (these use the `registry`/`platforms` inputs); use `ci_plan` to inspect/edit the plan first, or pass `phase_config_yaml` for a two-phase pipeline. - `ci_plan` description: minor — note secrets are scoped per phase (not just a union) and that `generate_github_actions` renders the plan in-process. -4. **`docs/mcp-tools-reference.md`** — add a `ci_plan` entry and a `generate_github_actions` entry mirroring the file's existing per-tool format (heading + one-line purpose + an inputs table). Inputs from the tool defs: `ci_plan` (`yaml_content` req, `phase_config_yaml`, `wfctl_version`); `generate_github_actions` (`yaml_content` req, `registry`, `platforms`). +4. **`docs/mcp-tools-reference.md`** — add a `ci_plan` entry and a `generate_github_actions` entry mirroring the file's existing per-tool format (heading + one-line purpose + an inputs table). Use the **exact** param names from the tool defs (NOT the doc's drifted `config`/`provider` naming): `ci_plan` — `yaml_content` (string, required), `phase_config_yaml` (string, optional), `wfctl_version` (string, optional); `generate_github_actions` — `yaml_content` (string, required), `registry` (string, optional, default `ghcr.io`), `platforms` (string, optional). **Also correct the adjacent stale `scaffold_ci` entry** (CI-adjacent, near-zero cost): the real tool (`mcp/scaffold_tools.go:20-28`) takes `description` (string, required) + `yaml_content` (string, optional) and emits a `ci:` section — drop the fictional `provider`/`circleci`/`config` params. **Out of scope (logged follow-up):** the `scaffold_environment` / `scaffold_infra` ref entries also drift from their tool defs but are not CI-related; leave them. + +5. **`mcp/setup_guide.go` "CI/CD Setup Flow"** (the `workflow://docs/setup-guide` resource) — resolve the competing-CI-story gap (I1). After the existing `scaffold_ci` → `generate_bootstrap` → `wfctl ci run` steps, add a short note distinguishing the two valid paths: (a) **thin bootstrap** — `scaffold_ci` emits a `ci:` config section and `generate_bootstrap` emits a minimal file that calls `wfctl ci run` (the engine runs the steps); (b) **config-derived platform-native workflow** — `ci_plan` + `generate_github_actions` (or `wfctl ci plan` / `ci generate`) render a full GitHub Actions / GitLab CI workflow from the config (scoped secrets, migrations, smoke, plan-guard). Pick (b) when you want a native CI YAML committed to the repo. Do not delete the existing flow — add the cigen alternative + the one-line "when to use which". ## 5. Testing - `GOWORK=off go build ./...` + `GOWORK=off go test ./mcp/...` — the `docsOverview` const is compile-time; tool descriptions are plain strings. Confirms nothing that enumerates tools/asserts metadata breaks (no test currently pins these strings — verified). -- **Runtime / multi-component:** build the MCP binary and start the server (`wfctl mcp`), then assert the rendered Instructions and the `workflow://docs/overview` resource contain "cigen"/"ci plan" and that the `generate_github_actions` tool description names cigen. (Add a focused `mcp` package test that calls `NewServer(...)` and asserts the Instructions string + the `docsOverview` const + the two tool descriptions contain the cigen keywords — exercises the real server, not a mock.) +- **Runtime / multi-component:** build the MCP binary and start the server (`wfctl mcp`), then assert the rendered Instructions, the `workflow://docs/overview` resource, and the `workflow://docs/setup-guide` resource contain "cigen"/"ci plan"/"ci generate" and that the `generate_github_actions` tool description names cigen. (Add a focused `mcp` package test — `NewServer("")` is dep-free and the proven pattern in `server_test.go` — asserting via `Contains`: the Instructions string, the `docsOverview` const, the `setupGuide` const, and the two tool descriptions carry the cigen keywords; and that `docsOverview` does NOT claim Jenkins/CircleCI are template-based.) - `GOWORK=off golangci-lint run --new-from-rev=origin/main ./mcp/...`. - Markdown: `docs/mcp-tools-reference.md` renders (no broken table). @@ -70,10 +73,11 @@ Real boundary = MCP server ↔ AI client. Proof: construct the real `mcp.NewServ ## Assumptions -1. `generate_github_actions` CI output is cigen-derived; `cd_yaml`/`release_yaml` are legacy template using `registry`/`platforms`. *(Verified: `mcp/wfctl_tools.go:416-453`.)* -2. No test pins the Instructions / tool-description / `docsOverview` strings verbatim. *(Verified by grep; the new assertion test will use `Contains`, not equality.)* -3. `docs/WFCTL.md` already documents `ci plan`/`ci generate`/cigen accurately, so MCP wording can mirror it. *(Verified: `docs/WFCTL.md:178,2140+`.)* -4. `docs/mcp-tools-reference.md` has a stable per-tool format (heading + purpose + inputs table) to mirror. *(Verified: e.g. `template_validate_config` entry.)* +1. `generate_github_actions` CI output is cigen-derived; `cd_yaml`/`release_yaml` are legacy template using `registry`/`platforms` — this is the ONLY hybrid. *(Verified: `mcp/wfctl_tools.go:416-453`.)* +2. All four CI platforms (`github_actions`, `gitlab_ci`, `jenkins`, `circleci`) are config-derived from the same CIPlan — no per-platform "smart vs template" split. *(Verified: `docs/WFCTL.md:2142`; RenderJenkins/RenderCircleCI per workflow#810/ADR 0044.)* +3. No test pins the Instructions / tool-description / `docsOverview` / `setupGuide` strings verbatim. *(Verified by grep; the new assertion test uses `Contains`, not equality. `NewServer("")` is dep-free — proven in `server_test.go`.)* +4. `docs/WFCTL.md` already documents `ci plan`/`ci generate`/cigen accurately, so MCP wording can mirror it. *(Verified: `docs/WFCTL.md:178,2140+`.)* +5. `docs/mcp-tools-reference.md` per-tool format is NOT uniform (some entries lack tables; param naming drifts `config` vs `yaml_content`; the `scaffold_ci` entry is stale). The plan mirrors the *table* entries and uses exact tool-def param names, and corrects the stale `scaffold_ci` entry. *(Verified: `scaffold_ci` ref entry `:201-208` vs tool `scaffold_tools.go:20-28`.)* ## Rollback From 080cbda6653c33fda8e3c0f11b1ca8b172e8b9db Mon Sep 17 00:00:00 2001 From: Jon Langevin Date: Thu, 4 Jun 2026 20:57:56 -0400 Subject: [PATCH 03/12] docs: mcp-cigen design PASS adversarial (2 cycles); clarify table-style ref entries Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/plans/2026-06-04-mcp-cigen-info-design.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/plans/2026-06-04-mcp-cigen-info-design.md b/docs/plans/2026-06-04-mcp-cigen-info-design.md index b67d5c51..6a90f318 100644 --- a/docs/plans/2026-06-04-mcp-cigen-info-design.md +++ b/docs/plans/2026-06-04-mcp-cigen-info-design.md @@ -1,7 +1,7 @@ # Surface cigen information in wfctl's MCP output — design **Date:** 2026-06-04 -**Status:** Design (adversarial review pending) +**Status:** Design — adversarial review PASS (2 cycles, 2026-06-04) **Repo:** `workflow` (the `mcp/` package + `docs/mcp-tools-reference.md`) **Guidance:** `docs/AGENT_GUIDE.md` + `CLAUDE.md` (no `docs/design-guidance.md`). @@ -38,7 +38,7 @@ MCP output (runtime Instructions + the `workflow://docs/overview` resource + the - `generate_github_actions` description: render CI via the cigen engine — config-derived (`files`/`ci_yaml`): per-phase scoped secrets, a `wfctl migrations up` step when `ci.migrations` is set, a smoke job, plugin-install steps, a plan-guard that fails on replace/destroy; also returns the `plan` (CIPlan) and **legacy template-based** `cd_yaml`/`release_yaml` (these use the `registry`/`platforms` inputs); use `ci_plan` to inspect/edit the plan first, or pass `phase_config_yaml` for a two-phase pipeline. - `ci_plan` description: minor — note secrets are scoped per phase (not just a union) and that `generate_github_actions` renders the plan in-process. -4. **`docs/mcp-tools-reference.md`** — add a `ci_plan` entry and a `generate_github_actions` entry mirroring the file's existing per-tool format (heading + one-line purpose + an inputs table). Use the **exact** param names from the tool defs (NOT the doc's drifted `config`/`provider` naming): `ci_plan` — `yaml_content` (string, required), `phase_config_yaml` (string, optional), `wfctl_version` (string, optional); `generate_github_actions` — `yaml_content` (string, required), `registry` (string, optional, default `ghcr.io`), `platforms` (string, optional). **Also correct the adjacent stale `scaffold_ci` entry** (CI-adjacent, near-zero cost): the real tool (`mcp/scaffold_tools.go:20-28`) takes `description` (string, required) + `yaml_content` (string, optional) and emits a `ci:` section — drop the fictional `provider`/`circleci`/`config` params. **Out of scope (logged follow-up):** the `scaffold_environment` / `scaffold_infra` ref entries also drift from their tool defs but are not CI-related; leave them. +4. **`docs/mcp-tools-reference.md`** — add a `ci_plan` entry and a `generate_github_actions` entry mirroring the file's existing table-style per-tool entries (heading + one-line purpose + an inputs table). Use the **exact** param names from the tool defs (NOT the doc's drifted `config`/`provider` naming): `ci_plan` — `yaml_content` (string, required), `phase_config_yaml` (string, optional), `wfctl_version` (string, optional); `generate_github_actions` — `yaml_content` (string, required), `registry` (string, optional, default `ghcr.io`), `platforms` (string, optional). **Also correct the adjacent stale `scaffold_ci` entry** (CI-adjacent, near-zero cost): the real tool (`mcp/scaffold_tools.go:20-28`) takes `description` (string, required) + `yaml_content` (string, optional) and emits a `ci:` section — drop the fictional `provider`/`circleci`/`config` params. **Out of scope (logged follow-up):** the `scaffold_environment` / `scaffold_infra` ref entries also drift from their tool defs but are not CI-related; leave them. 5. **`mcp/setup_guide.go` "CI/CD Setup Flow"** (the `workflow://docs/setup-guide` resource) — resolve the competing-CI-story gap (I1). After the existing `scaffold_ci` → `generate_bootstrap` → `wfctl ci run` steps, add a short note distinguishing the two valid paths: (a) **thin bootstrap** — `scaffold_ci` emits a `ci:` config section and `generate_bootstrap` emits a minimal file that calls `wfctl ci run` (the engine runs the steps); (b) **config-derived platform-native workflow** — `ci_plan` + `generate_github_actions` (or `wfctl ci plan` / `ci generate`) render a full GitHub Actions / GitLab CI workflow from the config (scoped secrets, migrations, smoke, plan-guard). Pick (b) when you want a native CI YAML committed to the repo. Do not delete the existing flow — add the cigen alternative + the one-line "when to use which". From 4bca1cfdd89062680001c4e0a967578d495a4e3e Mon Sep 17 00:00:00 2001 From: Jon Langevin Date: Thu, 4 Jun 2026 21:01:05 -0400 Subject: [PATCH 04/12] docs: implementation plan for surfacing cigen info in MCP output Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/plans/2026-06-04-mcp-cigen-info.md | 447 ++++++++++++++++++++++++ 1 file changed, 447 insertions(+) create mode 100644 docs/plans/2026-06-04-mcp-cigen-info.md diff --git a/docs/plans/2026-06-04-mcp-cigen-info.md b/docs/plans/2026-06-04-mcp-cigen-info.md new file mode 100644 index 00000000..ff8bfafa --- /dev/null +++ b/docs/plans/2026-06-04-mcp-cigen-info.md @@ -0,0 +1,447 @@ +# MCP cigen information surfacing Implementation Plan + +> **For the implementing agent:** REQUIRED SUB-SKILL: Use autodev:executing-plans to implement this plan task-by-task. + +**Goal:** Make wfctl's MCP output (server Instructions, the `workflow://docs/overview` + `workflow://docs/setup-guide` resources, the `ci_plan`/`generate_github_actions` tool descriptions) and `docs/mcp-tools-reference.md` accurately describe the config-derived cigen CI generation. + +**Architecture:** Edit static descriptive strings/consts in the `mcp` package + one markdown reference doc. The render path is already cigen-backed; this is informational only — no new tools, no handler/behavior change, no release. A focused `mcp`-package test (`Contains` assertions) locks the cigen keywords in. + +**Tech Stack:** Go (`mcp` package strings/consts), markdown (`docs/mcp-tools-reference.md`). + +**Base branch:** main (worktree branch `feat/mcp-cigen-info`) + +--- + +## Scope Manifest + +**PR Count:** 1 +**Tasks:** 7 +**Estimated Lines of Change:** ~120 (informational; not enforced) + +**Out of scope:** +- No new MCP tool (e.g. a `ci_generate`/from-plan render tool). Render already exists via `generate_github_actions`. +- No handler / CIPlan / behavior change; `registry`/`platforms` inputs unchanged. +- No edit to `docs/WFCTL.md` (already accurate; reused as the wording reference). +- The `generate_github_actions` handler reads `phase_config_yaml`/`wfctl_version` but its tool def does NOT declare them (latent schema gap) — NOT fixed here (would be a schema change); logged as a follow-up. The description therefore does NOT advertise `phase_config_yaml`. +- `scaffold_environment` / `scaffold_infra` ref-doc entries also drift from their defs but are not CI-related — left as a logged follow-up. + +**PR Grouping:** + +| PR # | Title | Tasks | Branch | +|------|-------|-------|--------| +| 1 | docs(mcp): surface cigen config-derived CI generation in MCP output | Task 1, Task 2, Task 3, Task 4, Task 5, Task 6, Task 7 | feat/mcp-cigen-info | + +**Status:** Draft + +--- + +### Task 1: Failing assertion test (mcp package) + +**Change class:** Internal logic / docs → unit test (`Contains`). + +**Files:** +- Create: `mcp/cigen_info_test.go` (NEW — `package mcp` internal so it can read the unexported `docsOverview`/`setupGuideContent` consts and call `NewServer`) + +**Step 1: Write the failing test** + +Create `mcp/cigen_info_test.go`: + +```go +package mcp + +import ( + "strings" + "testing" +) + +// TestMCPOutputSurfacesCigen locks the cigen config-derived CI information into +// the MCP output an AI client receives: the server Instructions, the +// workflow://docs/overview + workflow://docs/setup-guide resource bodies, and +// the ci_plan / generate_github_actions tool descriptions. +func TestMCPOutputSurfacesCigen(t *testing.T) { + // docsOverview resource: names the cigen CLI surface. + for _, want := range []string{"cigen", "wfctl ci plan", "wfctl ci generate", "config-derived"} { + if !strings.Contains(docsOverview, want) { + t.Errorf("docsOverview missing %q", want) + } + } + // Negative: must NOT claim Jenkins/CircleCI are template-based (all four are config-derived). + if strings.Contains(docsOverview, "Jenkins/CircleCI template") || + strings.Contains(docsOverview, "Jenkins and CircleCI are template") { + t.Errorf("docsOverview wrongly claims Jenkins/CircleCI are template-based") + } + + // setup-guide resource: surfaces the cigen path alongside the scaffold_ci flow. + for _, want := range []string{"ci_plan", "generate_github_actions", "wfctl ci generate"} { + if !strings.Contains(setupGuideContent, want) { + t.Errorf("setupGuideContent missing %q", want) + } + } + + // Server Instructions: mention cigen + ci_plan. + srv := NewServer("") + tools := srv.MCPServer().ListTools() + + gha, ok := tools["generate_github_actions"] + if !ok { + t.Fatal("generate_github_actions tool not registered") + } + for _, want := range []string{"cigen", "ci_plan"} { + if !strings.Contains(gha.Tool.Description, want) { + t.Errorf("generate_github_actions description missing %q", want) + } + } + ciPlan, ok := tools["ci_plan"] + if !ok { + t.Fatal("ci_plan tool not registered") + } + if !strings.Contains(ciPlan.Tool.Description, "cigen") { + t.Errorf("ci_plan description missing %q", "cigen") + } +} +``` + +> **Note on the Instructions string:** `NewServer` passes the Instructions to `server.NewMCPServer(...)`; the mcp-go API may not re-expose it on the constructed server. If `srv.MCPServer()` exposes no Instructions getter, assert the Instructions content by reading the source-level constant instead — extract the Instructions text into an unexported package const (e.g. `serverInstructions`) in Task 2 and assert `strings.Contains(serverInstructions, "cigen")` here. Decide in Task 2; keep the test asserting whatever Task 2 makes assertable. The tool-description and resource-const assertions above do not depend on this. + +**Step 2: Run to verify it fails** + +Run: `GOWORK=off go test ./mcp/ -run TestMCPOutputSurfacesCigen -v` +Expected: FAIL — `docsOverview missing "cigen"`, etc. (strings not yet added). + +**Step 3-4:** (no implementation in this task — it's the failing test; Tasks 2-5 make it pass.) + +**Step 5: Commit** + +```bash +git add mcp/cigen_info_test.go +git commit -m "test(mcp): assert MCP output surfaces cigen CI info (failing)" +``` + +--- + +### Task 2: Server Instructions (mcp/server.go) + +**Files:** +- Modify: `mcp/server.go` (the `server.WithInstructions(...)` call, ~line 104-115) + +**Change class:** internal logic (static string) → covered by Task 1 test. + +**Step 1: Implement** — replace the two trailing string fragments. Find: + +```go + "Use the registry_search tool to discover available plugins from the workflow-registry. "+ + "Resources provide documentation and example configurations. "+ + "The workflow engine includes a CLI tool called wfctl with commands for project scaffolding, "+ + "config validation, deployment (Docker, Kubernetes, cloud), API spec extraction, "+ + "diff/contract testing, CI/CD generation, plugin management, and Git integration. "+ + "Read the workflow://docs/overview resource for full CLI reference."), +``` + +Replace with: + +```go + "Use the registry_search tool to discover available plugins from the workflow-registry. "+ + "For CI/CD generation use the config-derived cigen engine (analyze -> CIPlan -> render): the "+ + "ci_plan tool analyzes a workflow config into a platform-neutral CIPlan (deploy phases, "+ + "secrets scoped per phase, a wfctl migrations step, a health-check smoke job, and a plan-guard), "+ + "and generate_github_actions renders it into GitHub Actions YAML - both produce CI derived "+ + "from the app config, NOT fixed templates. Mirrors the wfctl 'ci plan' / 'ci generate' commands. "+ + "Resources provide documentation and example configurations. "+ + "The workflow engine includes a CLI tool called wfctl with commands for project scaffolding, "+ + "config validation, deployment (Docker, Kubernetes, cloud), API spec extraction, "+ + "diff/contract testing, config-derived CI/CD generation (ci plan / ci generate), plugin management, and Git integration. "+ + "Read the workflow://docs/overview resource for full CLI reference."), +``` + +> If Task 1 needs a source-level constant to assert the Instructions (because mcp-go exposes no getter), first extract the whole instruction string into `const serverInstructions = "..."` above `NewServer` and pass `server.WithInstructions(serverInstructions)`. Otherwise leave inline. Either way the words "cigen" and "ci_plan" must appear. + +**Step 2: Verify** — `GOWORK=off go build ./mcp/` (compiles). The Task 1 assertion for the gha/ci_plan descriptions still fails until Task 4; that is expected. + +**Step 3: Commit** + +```bash +git add mcp/server.go +git commit -m "docs(mcp): name the cigen CI surface in server Instructions" +``` + +--- + +### Task 3: docsOverview CI/CD section (mcp/docs.go) + +**Files:** +- Modify: `mcp/docs.go` (`docsOverview` const, the "CI/CD & Git Integration" section ~line 165-169) + +**Change class:** internal logic (static const) → covered by Task 1 test (incl the negative Jenkins/CircleCI assertion). + +**Step 1: Implement** — replace the section. Find: + +```go +### CI/CD & Git Integration + +- ` + "`wfctl generate github-actions `" + ` — Generate GitHub Actions CI/CD workflow files from config +- ` + "`wfctl git connect -repo `" + ` — Link project to a GitHub repository (` + "`-init`" + ` to create repo) +- ` + "`wfctl git push -message `" + ` — Commit and push to configured repo (` + "`-tag `" + ` to tag release) +` +``` + +Replace with (mirrors `docs/WFCTL.md:2142` — all four platforms config-derived): + +```go +### CI/CD generation (config-derived via the cigen engine) + +CI generation is **config-derived**, not template-based: the cigen engine (analyze -> CIPlan -> +render) builds the workflow from your app config. The output reflects the config's required +secrets (scoped per deploy phase - an apply job only gets the secrets that phase references), a +` + "`wfctl migrations up`" + ` step when ` + "`ci.migrations`" + ` is declared (with ` + "`--format json`" + ` and ` + "`--env`" + ` when an +environment is unambiguous), a health-check smoke job, plugin-install steps when the app uses +plugins, and a plan-guard that fails the job on a replace/destroy. All four target platforms +(` + "`github_actions`" + `, ` + "`gitlab_ci`" + `, ` + "`jenkins`" + `, ` + "`circleci`" + `) are config-derived from the same CIPlan. + +- ` + "`wfctl ci plan `" + ` — Analyze the config and emit a platform-neutral CIPlan JSON (` + "`--out -`" + ` for stdout, ` + "`--phase-config `" + ` for a two-phase prereq->deploy plan). Edit it, then render with ` + "`--from-plan`" + `. +- ` + "`wfctl ci generate --platform github_actions`" + ` — Render CI files from the config (or ` + "`--from-plan `" + `). ` + "`--diff`" + ` previews vs the on-disk file; ` + "`--write`" + ` overwrites; ` + "`--out `" + ` sets the output directory. +- ` + "`wfctl generate github-actions `" + ` — Legacy command name; the CI workflow is now rendered through the same cigen engine. + +MCP equivalents: the ` + "`ci_plan`" + ` tool returns the CIPlan, and ` + "`generate_github_actions`" + ` renders it to GitHub Actions YAML. + +### Git Integration + +- ` + "`wfctl git connect -repo `" + ` — Link project to a GitHub repository (` + "`-init`" + ` to create repo) +- ` + "`wfctl git push -message `" + ` — Commit and push to configured repo (` + "`-tag `" + ` to tag release) +` +``` + +**Step 2: Verify** — `GOWORK=off go build ./mcp/`; `GOWORK=off go test ./mcp/ -run TestMCPOutputSurfacesCigen -v` now passes the `docsOverview` assertions (gha/ci_plan/setup-guide still pending Tasks 4-5). + +**Step 3: Commit** + +```bash +git add mcp/docs.go +git commit -m "docs(mcp): document config-derived cigen CI in docs/overview resource" +``` + +--- + +### Task 4: Tool descriptions (mcp/wfctl_tools.go) + +**Files:** +- Modify: `mcp/wfctl_tools.go` — `generate_github_actions` description (~line 136-137), `ci_plan` description (~line 155-158) + +**Change class:** internal logic (static strings) → covered by Task 1 test. + +**Step 1: Implement.** + +(a) `generate_github_actions` — find: + +```go + mcp.WithDescription("Generate GitHub Actions CI/CD workflow YAML files based on analysis of a workflow config. "+ + "Detects features (UI, auth, database, plugins, HTTP) and generates appropriate CI and CD workflows."), +``` + +Replace with: + +```go + mcp.WithDescription("Render CI/CD workflow YAML from a workflow config. The CI workflow (the 'files'/'ci_yaml' result) is config-derived via the cigen engine (analyze -> CIPlan -> render): required secrets scoped per deploy phase, a 'wfctl migrations up' step when ci.migrations is set, a health-check smoke job, plugin-install steps when plugins are used, and a plan-guard that fails on a replace/destroy - not a fixed template. Also returns the 'plan' (CIPlan) and legacy template-based 'cd_yaml'/'release_yaml' (these use the registry/platforms inputs). Use the ci_plan tool to inspect or edit the plan before rendering."), +``` + +(b) `ci_plan` — find: + +```go + mcp.WithDescription("Analyze a workflow YAML config and emit a platform-neutral CIPlan JSON. "+ + "The plan describes project name, wfctl version, deploy phases, secrets union, "+ + "migrations spec, smoke test URL, plan guard, and warnings. "+ + "Pass the returned JSON to 'wfctl ci generate --from-plan' to render CI files."), +``` + +Replace with: + +```go + mcp.WithDescription("Analyze a workflow YAML config and emit a platform-neutral CIPlan JSON using the config-derived cigen engine. "+ + "The plan describes project name, wfctl version, deploy phases (with secrets scoped per phase), the secrets union, "+ + "migrations spec, smoke test URL, plan guard, and warnings. "+ + "Render it with the generate_github_actions tool, or pass the JSON to 'wfctl ci generate --from-plan' to write CI files."), +``` + +**Step 2: Verify** — `GOWORK=off go test ./mcp/ -run TestMCPOutputSurfacesCigen -v` now passes the gha + ci_plan description assertions. + +**Step 3: Commit** + +```bash +git add mcp/wfctl_tools.go +git commit -m "docs(mcp): name cigen + hybrid CD in ci tool descriptions" +``` + +--- + +### Task 5: setup-guide CI/CD Setup Flow (mcp/setup_guide.go) + +**Files:** +- Modify: `mcp/setup_guide.go` (`setupGuideContent` const, "CI/CD Setup Flow" section ~line 61-72) + +**Change class:** internal logic (static const) → covered by Task 1 test. + +**Step 1: Implement** — find the "Validate" step that closes the flow: + +```go +4. **Validate** — use ` + "`validate_config`" + ` to check the final config + +--- +``` + +Replace with (add the two-paths note; keep the existing flow): + +```go +4. **Validate** — use ` + "`validate_config`" + ` to check the final config + +**Two CI paths:** +- *Thin bootstrap* (the steps above): ` + "`scaffold_ci`" + ` writes a ` + "`ci:`" + ` section and ` + "`generate_bootstrap`" + ` emits a minimal file that calls ` + "`wfctl ci run`" + ` (the engine runs the steps). +- *Config-derived platform-native workflow*: use ` + "`ci_plan`" + ` + ` + "`generate_github_actions`" + ` (or ` + "`wfctl ci plan`" + ` / ` + "`wfctl ci generate`" + `) to render a full GitHub Actions / GitLab CI workflow from the config - scoped secrets, migrations, smoke job, plan-guard. Pick this when you want a native CI YAML committed to the repo. + +--- +``` + +**Step 2: Verify** — `GOWORK=off go test ./mcp/ -run TestMCPOutputSurfacesCigen -v` now PASSES fully (all surfaces present). + +**Step 3: Commit** + +```bash +git add mcp/setup_guide.go +git commit -m "docs(mcp): add cigen path to setup-guide CI/CD flow" +``` + +--- + +### Task 6: MCP tools reference doc (docs/mcp-tools-reference.md) + +**Files:** +- Modify: `docs/mcp-tools-reference.md` — add `ci_plan` + `generate_github_actions` entries; correct the stale `scaffold_ci` entry (~line 201-208) + +**Change class:** Documentation → render/no-broken-table check. + +**Step 1: Correct the stale `scaffold_ci` entry.** Find: + +```markdown +#### `scaffold_ci` + +Generate CI/CD pipeline config for a workflow application. + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `provider` | string | yes | CI provider (`github-actions`, `gitlab-ci`, `circleci`) | +| `config` | string | no | Existing workflow config to analyze | +``` + +Replace with (real params from `mcp/scaffold_tools.go:20-37`): + +```markdown +#### `scaffold_ci` + +Generate a `ci:` YAML section (build / test / deploy sub-sections) for a workflow config, tailored to the app type. + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `description` | string | yes | Short description of the application (e.g. 'Go API server with Postgres') | +| `yaml_content` | string | no | Existing workflow config to analyze (used to detect app type) | +| `binary_path` | string | no | Go binary entrypoint path (default: `./cmd/server`) | +| `environments` | array | no | Deployment environment names to include (e.g. `['staging', 'production']`) | +``` + +**Step 2: Add the two CI tool entries.** Immediately after the corrected `scaffold_ci` entry (and its `---` separator), insert: + +```markdown +#### `ci_plan` + +Analyze a workflow config and emit a platform-neutral `CIPlan` JSON via the config-derived cigen engine (deploy phases with per-phase scoped secrets, migrations spec, smoke test, plan-guard, warnings). Render it with `generate_github_actions` or `wfctl ci generate --from-plan`. + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `yaml_content` | string | yes | The YAML content of the workflow configuration | +| `phase_config_yaml` | string | no | YAML of a prerequisite phase config (creates a two-phase plan) | +| `wfctl_version` | string | no | wfctl version to pin in the plan (default: latest) | + +--- + +#### `generate_github_actions` + +Render CI/CD workflow YAML from a workflow config. The CI workflow (`files`/`ci_yaml`) is config-derived via the cigen engine (scoped secrets, migrations step, smoke job, plan-guard); also returns the `plan` (CIPlan) and legacy template-based `cd_yaml`/`release_yaml` (which use the `registry`/`platforms` inputs). + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `yaml_content` | string | yes | The YAML content of the workflow configuration | +| `registry` | string | no | Container registry for the legacy CD/release output (default: `ghcr.io`) | +| `platforms` | string | no | Build platforms for the legacy CD/release output (default: `linux/amd64,linux/arm64`) | + +--- +``` + +(Exact insertion point is flexible — keep the three entries adjacent in the scaffold/CI area of the doc. Do not duplicate an existing heading.) + +**Step 2 (verify): no broken table / anchors.** + +Run: `GOWORK=off go test ./tests/... -run NoMachinePaths 2>/dev/null; grep -c "^#### \`ci_plan\`" docs/mcp-tools-reference.md` +Expected: the `ci_plan` heading count is `1` (added once); the file still parses (no stray pipe rows). Eyeball the three tables render. + +**Step 3: Commit** + +```bash +git add docs/mcp-tools-reference.md +git commit -m "docs: add ci_plan + generate_github_actions to MCP tools reference; fix stale scaffold_ci" +``` + +--- + +### Task 7: Full gate + runtime MCP launch check + +**Files:** none (verification task). + +**Change class:** Go-repo code change + multi-component (MCP server ↔ client boundary). + +**Step 1: Full mcp package + build.** + +Run: `GOWORK=off go test ./mcp/...` +Expected: `ok github.com/GoCodeAlone/workflow/mcp` (incl `TestMCPOutputSurfacesCigen`). + +Run: `GOWORK=off go build ./cmd/wfctl` +Expected: exit 0. + +**Step 2: Lint changed lines.** + +Run: `GOWORK=off golangci-lint run --new-from-rev=origin/main ./mcp/...` +Expected: exit 0. + +**Step 3: Runtime multi-component check — launch the real MCP server and confirm the output carries cigen.** The MCP server speaks JSON-RPC over stdio; the `initialize` response returns the Instructions, and `resources/read` returns the overview body. Drive it with a here-doc: + +```bash +GOWORK=off go build -o /tmp/wfctl-mcp ./cmd/wfctl +printf '%s\n' \ + '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"c","version":"0"}}}' \ + '{"jsonrpc":"2.0","method":"notifications/initialized"}' \ + '{"jsonrpc":"2.0","id":2,"method":"resources/read","params":{"uri":"workflow://docs/overview"}}' \ + | /tmp/wfctl-mcp mcp 2>/dev/null | grep -o "cigen" | head -1 +``` +Expected: prints `cigen` (the live server's `initialize` Instructions and/or the overview resource contain it). If `wfctl mcp` needs a flag/subcommand variation, confirm with `/tmp/wfctl-mcp mcp --help`; the goal is a real launched-server transcript showing the cigen string in the output an MCP client receives. Capture the transcript. + +**Step 4: Commit** (only if a doc tweak was needed; otherwise none). + +**Rollback (informational change):** revert the PR; the MCP reverts to the prior generic strings. No release, no state, no migration. + +--- + +## Global Design Guidance + +Source: `docs/AGENT_GUIDE.md` + `CLAUDE.md`. + +| guidance | response | +|---|---| +| Update docs with behavior/CLI/config changes (CLAUDE.md) | This is the doc/metadata accuracy fix itself; updates MCP runtime docs + `docs/mcp-tools-reference.md` | +| CI-gen changes touch `cigen/`, `cmd/wfctl/ci*.go`, `docs/WFCTL.md`, ci-generator (AGENT_GUIDE:48) | No CI-gen behavior change; MCP-side info only. `docs/WFCTL.md` already accurate (reused, not edited). No plugin/contract impact. | +| Use `GOWORK=off` for Go commands | All verification commands use `GOWORK=off`. | + +## Verification per change class + +- Tasks 2-5 (static strings/consts): covered by the Task 1 `Contains` test + `go build ./mcp/`. +- Task 6 (markdown): table renders, `ci_plan` heading added once. +- Task 7 (Go-repo + multi-component): full `go test ./mcp/...`, `go build ./cmd/wfctl`, `golangci-lint --new-from-rev`, and a **real launched MCP server** transcript showing the cigen string in the client-facing output (the MCP↔client boundary, not a mock). + +## Rollback + +Not a runtime-affecting change class (no build/deploy/version-pin/startup/migration/plugin-loading change). Rollback = revert the PR. No release, no state. From 069d6935ab348c411e0da52eb06b459a724ea372 Mon Sep 17 00:00:00 2001 From: Jon Langevin Date: Thu, 4 Jun 2026 21:05:30 -0400 Subject: [PATCH 05/12] chore: lock scope for mcp-cigen-info (alignment passed) Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/plans/2026-06-04-mcp-cigen-info.md | 2 +- docs/plans/2026-06-04-mcp-cigen-info.md.scope-lock | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 docs/plans/2026-06-04-mcp-cigen-info.md.scope-lock diff --git a/docs/plans/2026-06-04-mcp-cigen-info.md b/docs/plans/2026-06-04-mcp-cigen-info.md index ff8bfafa..d2f1b67b 100644 --- a/docs/plans/2026-06-04-mcp-cigen-info.md +++ b/docs/plans/2026-06-04-mcp-cigen-info.md @@ -31,7 +31,7 @@ |------|-------|-------|--------| | 1 | docs(mcp): surface cigen config-derived CI generation in MCP output | Task 1, Task 2, Task 3, Task 4, Task 5, Task 6, Task 7 | feat/mcp-cigen-info | -**Status:** Draft +**Status:** Locked 2026-06-05T01:05:30Z --- diff --git a/docs/plans/2026-06-04-mcp-cigen-info.md.scope-lock b/docs/plans/2026-06-04-mcp-cigen-info.md.scope-lock new file mode 100644 index 00000000..79a6eb8a --- /dev/null +++ b/docs/plans/2026-06-04-mcp-cigen-info.md.scope-lock @@ -0,0 +1 @@ +2d992e2e622762acab9c04aa3f7c6123d845749abcfa8d16c1f878d19c3fa3b4 From 9bbd1d8ba2fd48fcff259edf30ef8a7c66e1a3bb Mon Sep 17 00:00:00 2001 From: Jon Langevin Date: Thu, 4 Jun 2026 21:06:56 -0400 Subject: [PATCH 06/12] test(mcp): assert MCP output surfaces cigen CI info (failing) --- mcp/cigen_info_test.go | 52 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 mcp/cigen_info_test.go diff --git a/mcp/cigen_info_test.go b/mcp/cigen_info_test.go new file mode 100644 index 00000000..57ccd4cd --- /dev/null +++ b/mcp/cigen_info_test.go @@ -0,0 +1,52 @@ +package mcp + +import ( + "strings" + "testing" +) + +// TestMCPOutputSurfacesCigen locks the cigen config-derived CI information into +// the MCP output an AI client receives: the server Instructions, the +// workflow://docs/overview + workflow://docs/setup-guide resource bodies, and +// the ci_plan / generate_github_actions tool descriptions. +func TestMCPOutputSurfacesCigen(t *testing.T) { + // docsOverview resource: names the cigen CLI surface. + for _, want := range []string{"cigen", "wfctl ci plan", "wfctl ci generate", "config-derived"} { + if !strings.Contains(docsOverview, want) { + t.Errorf("docsOverview missing %q", want) + } + } + // Negative: must NOT claim Jenkins/CircleCI are template-based (all four are config-derived). + if strings.Contains(docsOverview, "Jenkins/CircleCI template") || + strings.Contains(docsOverview, "Jenkins and CircleCI are template") { + t.Errorf("docsOverview wrongly claims Jenkins/CircleCI are template-based") + } + + // setup-guide resource: surfaces the cigen path alongside the scaffold_ci flow. + for _, want := range []string{"ci_plan", "generate_github_actions", "wfctl ci generate"} { + if !strings.Contains(setupGuideContent, want) { + t.Errorf("setupGuideContent missing %q", want) + } + } + + // Server Instructions: mention cigen + ci_plan. + srv := NewServer("") + tools := srv.MCPServer().ListTools() + + gha, ok := tools["generate_github_actions"] + if !ok { + t.Fatal("generate_github_actions tool not registered") + } + for _, want := range []string{"cigen", "ci_plan"} { + if !strings.Contains(gha.Tool.Description, want) { + t.Errorf("generate_github_actions description missing %q", want) + } + } + ciPlan, ok := tools["ci_plan"] + if !ok { + t.Fatal("ci_plan tool not registered") + } + if !strings.Contains(ciPlan.Tool.Description, "cigen") { + t.Errorf("ci_plan description missing %q", "cigen") + } +} From 81cfb34c20edef6aabafb76564dcc91a5870f72e Mon Sep 17 00:00:00 2001 From: Jon Langevin Date: Thu, 4 Jun 2026 21:07:13 -0400 Subject: [PATCH 07/12] docs(mcp): name the cigen CI surface in server Instructions --- mcp/server.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/mcp/server.go b/mcp/server.go index b5c9ed37..0bfb6ae5 100644 --- a/mcp/server.go +++ b/mcp/server.go @@ -108,10 +108,15 @@ func NewServer(pluginDir string, opts ...ServerOption) *Server { "anti-patterns (hyphenated step names, template syntax in conditionals, missing db_query mode, "+ "dot-access patterns, absolute dbPaths, empty routes, snake_case config keys). "+ "Use the registry_search tool to discover available plugins from the workflow-registry. "+ + "For CI/CD generation use the config-derived cigen engine (analyze -> CIPlan -> render): the "+ + "ci_plan tool analyzes a workflow config into a platform-neutral CIPlan (deploy phases, "+ + "secrets scoped per phase, a wfctl migrations step, a health-check smoke job, and a plan-guard), "+ + "and generate_github_actions renders it into GitHub Actions YAML - both produce CI derived "+ + "from the app config, NOT fixed templates. Mirrors the wfctl 'ci plan' / 'ci generate' commands. "+ "Resources provide documentation and example configurations. "+ "The workflow engine includes a CLI tool called wfctl with commands for project scaffolding, "+ "config validation, deployment (Docker, Kubernetes, cloud), API spec extraction, "+ - "diff/contract testing, CI/CD generation, plugin management, and Git integration. "+ + "diff/contract testing, config-derived CI/CD generation (ci plan / ci generate), plugin management, and Git integration. "+ "Read the workflow://docs/overview resource for full CLI reference."), ) From 4bb01fe313af1e51315753a7c84de9142770deac Mon Sep 17 00:00:00 2001 From: Jon Langevin Date: Thu, 4 Jun 2026 21:07:52 -0400 Subject: [PATCH 08/12] docs(mcp): document config-derived cigen CI in docs/overview resource --- mcp/docs.go | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/mcp/docs.go b/mcp/docs.go index e8566d25..1ee4f625 100644 --- a/mcp/docs.go +++ b/mcp/docs.go @@ -162,9 +162,24 @@ trigger types, and workflow handlers. Plugins can be: - ` + "`wfctl migrate diff -db `" + ` — Show pending migrations without applying - ` + "`wfctl migrate apply -db `" + ` — Apply pending migrations -### CI/CD & Git Integration +### CI/CD generation (config-derived via the cigen engine) + +CI generation is **config-derived**, not template-based: the cigen engine (analyze -> CIPlan -> +render) builds the workflow from your app config. The output reflects the config's required +secrets (scoped per deploy phase - an apply job only gets the secrets that phase references), a +` + "`wfctl migrations up`" + ` step when ` + "`ci.migrations`" + ` is declared (with ` + "`--format json`" + ` and ` + "`--env`" + ` when an +environment is unambiguous), a health-check smoke job, plugin-install steps when the app uses +plugins, and a plan-guard that fails the job on a replace/destroy. All four target platforms +(` + "`github_actions`" + `, ` + "`gitlab_ci`" + `, ` + "`jenkins`" + `, ` + "`circleci`" + `) are config-derived from the same CIPlan. + +- ` + "`wfctl ci plan `" + ` — Analyze the config and emit a platform-neutral CIPlan JSON (` + "`--out -`" + ` for stdout, ` + "`--phase-config `" + ` for a two-phase prereq->deploy plan). Edit it, then render with ` + "`--from-plan`" + `. +- ` + "`wfctl ci generate --platform github_actions`" + ` — Render CI files from the config (or ` + "`--from-plan `" + `). ` + "`--diff`" + ` previews vs the on-disk file; ` + "`--write`" + ` overwrites; ` + "`--out `" + ` sets the output directory. +- ` + "`wfctl generate github-actions `" + ` — Legacy command name; the CI workflow is now rendered through the same cigen engine. + +MCP equivalents: the ` + "`ci_plan`" + ` tool returns the CIPlan, and ` + "`generate_github_actions`" + ` renders it to GitHub Actions YAML. + +### Git Integration -- ` + "`wfctl generate github-actions `" + ` — Generate GitHub Actions CI/CD workflow files from config - ` + "`wfctl git connect -repo `" + ` — Link project to a GitHub repository (` + "`-init`" + ` to create repo) - ` + "`wfctl git push -message `" + ` — Commit and push to configured repo (` + "`-tag `" + ` to tag release) ` From 62a04d68bd714daef482ff0a6f2e3f228752cfa8 Mon Sep 17 00:00:00 2001 From: Jon Langevin Date: Thu, 4 Jun 2026 21:08:29 -0400 Subject: [PATCH 09/12] docs(mcp): name cigen + hybrid CD in ci tool descriptions --- mcp/wfctl_tools.go | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/mcp/wfctl_tools.go b/mcp/wfctl_tools.go index fae08d78..203a80b0 100644 --- a/mcp/wfctl_tools.go +++ b/mcp/wfctl_tools.go @@ -133,8 +133,7 @@ func (s *Server) registerWfctlTools() { s.mcpServer.AddTool( mcp.NewTool("generate_github_actions", - mcp.WithDescription("Generate GitHub Actions CI/CD workflow YAML files based on analysis of a workflow config. "+ - "Detects features (UI, auth, database, plugins, HTTP) and generates appropriate CI and CD workflows."), + mcp.WithDescription("Render CI/CD workflow YAML from a workflow config. The CI workflow (the 'files'/'ci_yaml' result) is config-derived via the cigen engine (analyze -> CIPlan -> render): required secrets scoped per deploy phase, a 'wfctl migrations up' step when ci.migrations is set, a health-check smoke job, plugin-install steps when plugins are used, and a plan-guard that fails on a replace/destroy - not a fixed template. Also returns the 'plan' (CIPlan) and legacy template-based 'cd_yaml'/'release_yaml' (these use the registry/platforms inputs). Use the ci_plan tool to inspect or edit the plan before rendering."), mcp.WithString("yaml_content", mcp.Required(), mcp.Description("The YAML content of the workflow configuration"), @@ -152,10 +151,10 @@ func (s *Server) registerWfctlTools() { s.mcpServer.AddTool( mcp.NewTool("ci_plan", - mcp.WithDescription("Analyze a workflow YAML config and emit a platform-neutral CIPlan JSON. "+ - "The plan describes project name, wfctl version, deploy phases, secrets union, "+ + mcp.WithDescription("Analyze a workflow YAML config and emit a platform-neutral CIPlan JSON using the config-derived cigen engine. "+ + "The plan describes project name, wfctl version, deploy phases (with secrets scoped per phase), the secrets union, "+ "migrations spec, smoke test URL, plan guard, and warnings. "+ - "Pass the returned JSON to 'wfctl ci generate --from-plan' to render CI files."), + "Render it with the generate_github_actions tool, or pass the JSON to 'wfctl ci generate --from-plan' to write CI files."), mcp.WithString("yaml_content", mcp.Required(), mcp.Description("The YAML content of the workflow configuration"), From 356c1eab6a535a787433802cf79230927e185549 Mon Sep 17 00:00:00 2001 From: Jon Langevin Date: Thu, 4 Jun 2026 21:08:51 -0400 Subject: [PATCH 10/12] docs(mcp): add cigen path to setup-guide CI/CD flow --- mcp/setup_guide.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mcp/setup_guide.go b/mcp/setup_guide.go index 0147a0c1..2690f273 100644 --- a/mcp/setup_guide.go +++ b/mcp/setup_guide.go @@ -71,6 +71,10 @@ When a user wants automated deployment: 4. **Validate** — use ` + "`validate_config`" + ` to check the final config +**Two CI paths:** +- *Thin bootstrap* (the steps above): ` + "`scaffold_ci`" + ` writes a ` + "`ci:`" + ` section and ` + "`generate_bootstrap`" + ` emits a minimal file that calls ` + "`wfctl ci run`" + ` (the engine runs the steps). +- *Config-derived platform-native workflow*: use ` + "`ci_plan`" + ` + ` + "`generate_github_actions`" + ` (or ` + "`wfctl ci plan`" + ` / ` + "`wfctl ci generate`" + `) to render a full GitHub Actions / GitLab CI workflow from the config - scoped secrets, migrations, smoke job, plan-guard. Pick this when you want a native CI YAML committed to the repo. + --- ## Secrets Management Flow From aa64ba2e12b06335c1b00ace525964db4f8fa589 Mon Sep 17 00:00:00 2001 From: Jon Langevin Date: Thu, 4 Jun 2026 21:09:14 -0400 Subject: [PATCH 11/12] docs: add ci_plan + generate_github_actions to MCP tools reference; fix stale scaffold_ci --- docs/mcp-tools-reference.md | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/docs/mcp-tools-reference.md b/docs/mcp-tools-reference.md index 3fddbb15..1d95ba2c 100644 --- a/docs/mcp-tools-reference.md +++ b/docs/mcp-tools-reference.md @@ -200,12 +200,38 @@ Generate a JSON Schema for workflow config files. #### `scaffold_ci` -Generate CI/CD pipeline config for a workflow application. +Generate a `ci:` YAML section (build / test / deploy sub-sections) for a workflow config, tailored to the app type. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| -| `provider` | string | yes | CI provider (`github-actions`, `gitlab-ci`, `circleci`) | -| `config` | string | no | Existing workflow config to analyze | +| `description` | string | yes | Short description of the application (e.g. 'Go API server with Postgres') | +| `yaml_content` | string | no | Existing workflow config to analyze (used to detect app type) | +| `binary_path` | string | no | Go binary entrypoint path (default: `./cmd/server`) | +| `environments` | array | no | Deployment environment names to include (e.g. `['staging', 'production']`) | + +--- + +#### `ci_plan` + +Analyze a workflow config and emit a platform-neutral `CIPlan` JSON via the config-derived cigen engine (deploy phases with per-phase scoped secrets, migrations spec, smoke test, plan-guard, warnings). Render it with `generate_github_actions` or `wfctl ci generate --from-plan`. + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `yaml_content` | string | yes | The YAML content of the workflow configuration | +| `phase_config_yaml` | string | no | YAML of a prerequisite phase config (creates a two-phase plan) | +| `wfctl_version` | string | no | wfctl version to pin in the plan (default: latest) | + +--- + +#### `generate_github_actions` + +Render CI/CD workflow YAML from a workflow config. The CI workflow (`files`/`ci_yaml`) is config-derived via the cigen engine (scoped secrets, migrations step, smoke job, plan-guard); also returns the `plan` (CIPlan) and legacy template-based `cd_yaml`/`release_yaml` (which use the `registry`/`platforms` inputs). + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `yaml_content` | string | yes | The YAML content of the workflow configuration | +| `registry` | string | no | Container registry for the legacy CD/release output (default: `ghcr.io`) | +| `platforms` | string | no | Build platforms for the legacy CD/release output (default: `linux/amd64,linux/arm64`) | --- From 7e81d801e38518a2eef0b4d8421bc3e1562292f8 Mon Sep 17 00:00:00 2001 From: Jon Langevin Date: Thu, 4 Jun 2026 21:29:44 -0400 Subject: [PATCH 12/12] =?UTF-8?q?docs(mcp):=20address=20Copilot=20review?= =?UTF-8?q?=20=E2=80=94=20accurate=20render-tool=20semantics?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - generate_github_actions/ci_plan descriptions: clarify the tool re-analyzes the config and renders GitHub Actions ONLY; it does NOT accept a pre-built/edited CIPlan — rendering an edited plan or GitLab CI is the wfctl CLI (--from-plan / --platform gitlab_ci). Fixes the misleading 'edit the plan then render via MCP'. - setup-guide: same GHA-only / CLI-for-GitLab clarification. - extract serverInstructions package const + assert it in the test so the Instructions are genuinely locked (the test previously only claimed to). Co-Authored-By: Claude Opus 4.8 (1M context) --- mcp/cigen_info_test.go | 10 +++++++++- mcp/server.go | 39 ++++++++++++++++++++++----------------- mcp/setup_guide.go | 2 +- mcp/wfctl_tools.go | 4 ++-- 4 files changed, 34 insertions(+), 21 deletions(-) diff --git a/mcp/cigen_info_test.go b/mcp/cigen_info_test.go index 57ccd4cd..c195ca18 100644 --- a/mcp/cigen_info_test.go +++ b/mcp/cigen_info_test.go @@ -29,7 +29,15 @@ func TestMCPOutputSurfacesCigen(t *testing.T) { } } - // Server Instructions: mention cigen + ci_plan. + // Server Instructions (sent to clients in the initialize response): name the + // cigen surface. Asserted via the package const because mcp-go exposes no + // Instructions getter on the constructed server. + for _, want := range []string{"cigen", "ci_plan", "config-derived"} { + if !strings.Contains(serverInstructions, want) { + t.Errorf("serverInstructions missing %q", want) + } + } + srv := NewServer("") tools := srv.MCPServer().ListTools() diff --git a/mcp/server.go b/mcp/server.go index 0bfb6ae5..c3c27adc 100644 --- a/mcp/server.go +++ b/mcp/server.go @@ -82,6 +82,27 @@ type Server struct { toolHandlers map[string]ToolHandlerFunc // populated by collectToolHandlers } +// serverInstructions is the MCP server's instruction string sent to clients in +// the initialize response. Kept as a package const so tests can assert its +// content (the mcp-go server exposes no Instructions getter at runtime). +const serverInstructions = "This MCP server exposes the GoCodeAlone/workflow engine via wfctl. " + + "Use the provided tools to list available module types, step types, trigger types, " + + "workflow types, generate JSON schemas, validate YAML configurations, inspect configs, " + + "and manage plugins. Use the modernize tool to detect and fix known YAML config " + + "anti-patterns (hyphenated step names, template syntax in conditionals, missing db_query mode, " + + "dot-access patterns, absolute dbPaths, empty routes, snake_case config keys). " + + "Use the registry_search tool to discover available plugins from the workflow-registry. " + + "For CI/CD generation use the config-derived cigen engine (analyze -> CIPlan -> render): the " + + "ci_plan tool analyzes a workflow config into a platform-neutral CIPlan (deploy phases, " + + "secrets scoped per phase, a wfctl migrations step, a health-check smoke job, and a plan-guard), " + + "and generate_github_actions renders it into GitHub Actions YAML - both produce CI derived " + + "from the app config, NOT fixed templates. Mirrors the wfctl 'ci plan' / 'ci generate' commands. " + + "Resources provide documentation and example configurations. " + + "The workflow engine includes a CLI tool called wfctl with commands for project scaffolding, " + + "config validation, deployment (Docker, Kubernetes, cloud), API spec extraction, " + + "diff/contract testing, config-derived CI/CD generation (ci plan / ci generate), plugin management, and Git integration. " + + "Read the workflow://docs/overview resource for full CLI reference." + // NewServer creates a new MCP server with all workflow engine tools and // resources registered. pluginDir is the directory where installed plugins // reside (e.g., "data/plugins"). If set, the server will read plugin manifests @@ -101,23 +122,7 @@ func NewServer(pluginDir string, opts ...ServerOption) *Server { Version, server.WithToolCapabilities(true), server.WithResourceCapabilities(false, true), - server.WithInstructions("This MCP server exposes the GoCodeAlone/workflow engine via wfctl. "+ - "Use the provided tools to list available module types, step types, trigger types, "+ - "workflow types, generate JSON schemas, validate YAML configurations, inspect configs, "+ - "and manage plugins. Use the modernize tool to detect and fix known YAML config "+ - "anti-patterns (hyphenated step names, template syntax in conditionals, missing db_query mode, "+ - "dot-access patterns, absolute dbPaths, empty routes, snake_case config keys). "+ - "Use the registry_search tool to discover available plugins from the workflow-registry. "+ - "For CI/CD generation use the config-derived cigen engine (analyze -> CIPlan -> render): the "+ - "ci_plan tool analyzes a workflow config into a platform-neutral CIPlan (deploy phases, "+ - "secrets scoped per phase, a wfctl migrations step, a health-check smoke job, and a plan-guard), "+ - "and generate_github_actions renders it into GitHub Actions YAML - both produce CI derived "+ - "from the app config, NOT fixed templates. Mirrors the wfctl 'ci plan' / 'ci generate' commands. "+ - "Resources provide documentation and example configurations. "+ - "The workflow engine includes a CLI tool called wfctl with commands for project scaffolding, "+ - "config validation, deployment (Docker, Kubernetes, cloud), API spec extraction, "+ - "diff/contract testing, config-derived CI/CD generation (ci plan / ci generate), plugin management, and Git integration. "+ - "Read the workflow://docs/overview resource for full CLI reference."), + server.WithInstructions(serverInstructions), ) // Load types from installed plugin manifests so that plugin-provided types diff --git a/mcp/setup_guide.go b/mcp/setup_guide.go index 2690f273..b4c7b621 100644 --- a/mcp/setup_guide.go +++ b/mcp/setup_guide.go @@ -73,7 +73,7 @@ When a user wants automated deployment: **Two CI paths:** - *Thin bootstrap* (the steps above): ` + "`scaffold_ci`" + ` writes a ` + "`ci:`" + ` section and ` + "`generate_bootstrap`" + ` emits a minimal file that calls ` + "`wfctl ci run`" + ` (the engine runs the steps). -- *Config-derived platform-native workflow*: use ` + "`ci_plan`" + ` + ` + "`generate_github_actions`" + ` (or ` + "`wfctl ci plan`" + ` / ` + "`wfctl ci generate`" + `) to render a full GitHub Actions / GitLab CI workflow from the config - scoped secrets, migrations, smoke job, plan-guard. Pick this when you want a native CI YAML committed to the repo. +- *Config-derived platform-native workflow*: use ` + "`ci_plan`" + ` to build the CIPlan and ` + "`generate_github_actions`" + ` to render **GitHub Actions** (the MCP render tool is GitHub-Actions-only) - scoped secrets, migrations, smoke job, plan-guard. For GitLab CI / other platforms, or to render an edited plan, use the wfctl CLI: ` + "`wfctl ci generate --platform [--from-plan ]`" + `. Pick this when you want a native CI YAML committed to the repo. --- diff --git a/mcp/wfctl_tools.go b/mcp/wfctl_tools.go index 203a80b0..3f6b9976 100644 --- a/mcp/wfctl_tools.go +++ b/mcp/wfctl_tools.go @@ -133,7 +133,7 @@ func (s *Server) registerWfctlTools() { s.mcpServer.AddTool( mcp.NewTool("generate_github_actions", - mcp.WithDescription("Render CI/CD workflow YAML from a workflow config. The CI workflow (the 'files'/'ci_yaml' result) is config-derived via the cigen engine (analyze -> CIPlan -> render): required secrets scoped per deploy phase, a 'wfctl migrations up' step when ci.migrations is set, a health-check smoke job, plugin-install steps when plugins are used, and a plan-guard that fails on a replace/destroy - not a fixed template. Also returns the 'plan' (CIPlan) and legacy template-based 'cd_yaml'/'release_yaml' (these use the registry/platforms inputs). Use the ci_plan tool to inspect or edit the plan before rendering."), + mcp.WithDescription("Render CI/CD workflow YAML from a workflow config. The CI workflow (the 'files'/'ci_yaml' result) is config-derived via the cigen engine (analyze -> CIPlan -> render): required secrets scoped per deploy phase, a 'wfctl migrations up' step when ci.migrations is set, a health-check smoke job, plugin-install steps when plugins are used, and a plan-guard that fails on a replace/destroy - not a fixed template. Also returns the 'plan' (CIPlan) and legacy template-based 'cd_yaml'/'release_yaml' (these use the registry/platforms inputs). This tool re-analyzes the config on each call and renders GitHub Actions ONLY - it does NOT accept a pre-built/edited CIPlan. Use the ci_plan tool to preview the CIPlan; to render an edited plan or a GitLab CI workflow, use the wfctl CLI ('wfctl ci generate --from-plan' / '--platform gitlab_ci')."), mcp.WithString("yaml_content", mcp.Required(), mcp.Description("The YAML content of the workflow configuration"), @@ -154,7 +154,7 @@ func (s *Server) registerWfctlTools() { mcp.WithDescription("Analyze a workflow YAML config and emit a platform-neutral CIPlan JSON using the config-derived cigen engine. "+ "The plan describes project name, wfctl version, deploy phases (with secrets scoped per phase), the secrets union, "+ "migrations spec, smoke test URL, plan guard, and warnings. "+ - "Render it with the generate_github_actions tool, or pass the JSON to 'wfctl ci generate --from-plan' to write CI files."), + "To render: the generate_github_actions tool renders GitHub Actions from the same config (it re-analyzes - it does NOT consume this JSON); to render THIS plan JSON (e.g. after editing) or other platforms, use the wfctl CLI 'wfctl ci generate --from-plan'."), mcp.WithString("yaml_content", mcp.Required(), mcp.Description("The YAML content of the workflow configuration"),