From af3acdc6a969ecb1299e4ef0de790923309d3e84 Mon Sep 17 00:00:00 2001 From: Alexandr Zaytsev Date: Tue, 11 Aug 2026 21:58:30 +0300 Subject: [PATCH 1/2] chore(dev): add docker agent conf for speckit execution loop MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Define root, executor, and verifier agents to orchestrate the implement → converge cycle for spec-driven development. --- .cagent/speckit-execution-loop/config.yaml | 125 ++++++++++++++++++ .../instructions-executor.md | 9 ++ .../instructions-root.md | 29 ++++ .../instructions-verifier.md | 7 + 4 files changed, 170 insertions(+) create mode 100644 .cagent/speckit-execution-loop/config.yaml create mode 100644 .cagent/speckit-execution-loop/instructions-executor.md create mode 100644 .cagent/speckit-execution-loop/instructions-root.md create mode 100644 .cagent/speckit-execution-loop/instructions-verifier.md diff --git a/.cagent/speckit-execution-loop/config.yaml b/.cagent/speckit-execution-loop/config.yaml new file mode 100644 index 0000000000..0910b097be --- /dev/null +++ b/.cagent/speckit-execution-loop/config.yaml @@ -0,0 +1,125 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/docker/docker-agent/main/agent-schema.json +version: 15 + +permissions: + allow: + - "shell:cmd=jq*" + - "shell:cmd=wc*" + - "shell:cmd=git*" + - "shell:cmd=python3 .specify/scripts/python/*" + +agents: + # root — execution loop coordinator + root: + model: flant/deepseek-v4-flash + description: SDD execution loop. It orchestrates implement → converge loop + instruction_file: instructions-root.md + + sub_agents: [executor, verifier] + + # autonomous is safe because global ~/.config/cagent/config.yaml + # covers restrictions: deny rules for sudo*, rm -rf*, chmod*, etc. + safety: autonomous + + toolsets: + - type: filesystem + # filesystem access scoped to current repo; global deny rules + # (e.g. write to /etc/**, delete_path outside repo) are enforced + # at the user config level + allow_list: ["."] + + - type: shell + + # executor — runs speckit-implement + executor: + model: flant/deepseek-v4-flash + description: Implements features via speckit-implement + instruction_file: instructions-executor.md + + skills: + - speckit-implement + + # autonomous is safe because global ~/.config/cagent/config.yaml + # covers restrictions: deny rules for sudo*, rm -rf*, chmod*, etc. + safety: autonomous + + toolsets: + - type: script + shell: + lint: + cmd: task lint + description: Run all linters (golangci-lint, etc.) + + format: + cmd: task format paths=${paths} + description: Format Go source code + args: + paths: + type: string + description: Target directory to format (e.g. pkg/foo) + + mock-gen: + cmd: task mock:generate + description: Generate Go mock files via mockgen + + doc-gen: + cmd: task doc:gen + description: Generate CLI reference documentation + + test-unit: + cmd: task test:unit paths=${paths} -- -focus=${focus} + description: Run unit tests with optional package paths and focus filter + args: + paths: + type: string + description: Package paths (e.g. ./pkg/...) + focus: + type: string + description: Ginkgo focus pattern for test selection + + test-e2e: + cmd: task test:e2e paths=${paths} labelFilter=${labelFilter} + description: Run e2e tests with optional package paths and label filter + args: + paths: + type: string + description: E2e test package paths (e.g. ./test/e2e/sbom/...) + labelFilter: + type: string + description: Ginkgo label filter for test selection (e.g. sbom) + + - type: filesystem + allow_list: ["."] + + - type: shell + + - type: mcp + command: godoc-mcp + env: + GOPATH: ${HOME}/go + GOMODCACHE: ${HOME}/go/pkg/mod + GOROOT: /snap/go/current + instruction: Go documentation lookup via godoc-mcp + + - type: lsp + command: gopls + file_types: [".go"] + instruction: Go language server for code intelligence + + # verifier — runs speckit-converge + verifier: + model: flant/deepseek-v4-flash + description: Verifies implementation convergence via speckit-converge + instruction_file: instructions-verifier.md + + skills: + - speckit-converge + + # autonomous is safe because global ~/.config/cagent/config.yaml + # covers restrictions: deny rules for sudo*, rm -rf*, chmod*, etc. + safety: autonomous + + toolsets: + - type: filesystem + allow_list: ["."] + - type: shell diff --git a/.cagent/speckit-execution-loop/instructions-executor.md b/.cagent/speckit-execution-loop/instructions-executor.md new file mode 100644 index 0000000000..459f53bf03 --- /dev/null +++ b/.cagent/speckit-execution-loop/instructions-executor.md @@ -0,0 +1,9 @@ +# Executor Agent + +You implement features using spec-kit. + +## Task + +When you receive a task, run `/speckit-implement` and wait for it to complete. + +Use the available tools (script tasks, filesystem, MCP, LSP, shell) to assist the implementation. \ No newline at end of file diff --git a/.cagent/speckit-execution-loop/instructions-root.md b/.cagent/speckit-execution-loop/instructions-root.md new file mode 100644 index 0000000000..f955996b5f --- /dev/null +++ b/.cagent/speckit-execution-loop/instructions-root.md @@ -0,0 +1,29 @@ +# Root Agent — Execution Loop + +You are the execution loop coordinator for spec-driven development in the delivery-kit (werf) project. Your role is to drive the implement → converge → check cycle by delegating to sub-agents. + +## Loop + +1. Read `FEATURE_DIR` from `.specify/feature.json` using `jq -r '.feature_directory' .specify/feature.json`. + Let `TASKS_FILE = specs/${FEATURE_DIR}/tasks.md` + +2. Remember current line count: `wc -l < ${TASKS_FILE}` → save as PREV_COUNT + +3. Delegate implementation to `executor`: + - Use `transfer_task` with agent: `"executor"`, task: `"Run /speckit-implement"` + - Wait for the result + +4. Delegate convergence check to `verifier`: + - Use `transfer_task` with agent: `"verifier"`, task: `"Run /speckit-converge"` + - Wait for the result + +5. Check current line count: `wc -l < ${TASKS_FILE}` → save as CURR_COUNT + +6. If CURR_COUNT != PREV_COUNT → go to step 2 + +7. Otherwise → report completion with a summary of implemented work + +## Important Rules + +- Never modify `spec.md`, `plan.md`, `tasks.md` or `feature.json` directly. +- If a sub-agent task fails or returns an error, report it and stop the loop. diff --git a/.cagent/speckit-execution-loop/instructions-verifier.md b/.cagent/speckit-execution-loop/instructions-verifier.md new file mode 100644 index 0000000000..6dd7028ac6 --- /dev/null +++ b/.cagent/speckit-execution-loop/instructions-verifier.md @@ -0,0 +1,7 @@ +# Verifier Agent + +You verify that the implementation satisfies the specification. + +## Task + +When you receive a task, run `/speckit-converge` and wait for it to complete. \ No newline at end of file From 1f779a456eb6f964019fe2b07e4a61c32a0f9b14 Mon Sep 17 00:00:00 2001 From: Alexandr Zaytsev Date: Wed, 12 Aug 2026 20:59:32 +0300 Subject: [PATCH 2/2] chore(dev): deduplicate agent toolset definitions Define shared toolsets under `toolsets` and reference them per agent via `use_toolsets`, replacing duplicated inline definitions. Move `safety: autonomous` into the runtime section as the config-wide default and restrict top-level shell permissions to jq and a scoped python script pattern. Update the root agent loop to delegate implementation before reading feature state, compare tasks.md byte counts instead of line counts, and pass user input on the first iteration. --- .cagent/speckit-execution-loop/config.yaml | 177 +++++++++--------- .../instructions-root.md | 29 +-- 2 files changed, 104 insertions(+), 102 deletions(-) diff --git a/.cagent/speckit-execution-loop/config.yaml b/.cagent/speckit-execution-loop/config.yaml index 0910b097be..e18579a217 100644 --- a/.cagent/speckit-execution-loop/config.yaml +++ b/.cagent/speckit-execution-loop/config.yaml @@ -4,9 +4,91 @@ version: 15 permissions: allow: - "shell:cmd=jq*" - - "shell:cmd=wc*" - - "shell:cmd=git*" - - "shell:cmd=python3 .specify/scripts/python/*" + - "shell:cmd=python3 .specify/scripts/python/[_a-z]+.py" + +runtime: + # autonomous is safe because global ~/.config/cagent/config.yaml + # covers restrictions: deny rules for sudo*, rm -rf*, chmod*, etc. + safety: autonomous # config-wide default for new sessions + +# ============================================================ +# Shared Toolsets +# ============================================================ + +toolsets: + fs-scoped: + type: filesystem + # filesystem access scoped to current repo; global deny rules + # (e.g. write to /etc/**, delete_path outside repo) are enforced + # at the user config level + allow_list: ["."] + + shell-tool: + type: shell + + script-tools: + type: script + shell: + lint: + cmd: task lint + description: Run all linters (golangci-lint, etc.) + + format: + cmd: task format paths=${paths} + description: Format Go source code + args: + paths: + type: string + description: Target directory to format (e.g. pkg/foo) + + mock-gen: + cmd: task mock:generate + description: Generate Go mock files via mockgen + + doc-gen: + cmd: task doc:gen + description: Generate CLI reference documentation + + test-unit: + cmd: task test:unit paths=${paths} -- -focus=${focus} + description: Run unit tests with optional package paths and focus filter + args: + paths: + type: string + description: Package paths (e.g. ./pkg/...) + focus: + type: string + description: Ginkgo focus pattern for test selection + + test-e2e: + cmd: task test:e2e paths=${paths} labelFilter=${labelFilter} + description: Run e2e tests with optional package paths and label filter + args: + paths: + type: string + description: E2e test package paths (e.g. ./test/e2e/sbom/...) + labelFilter: + type: string + description: Ginkgo label filter for test selection (e.g. sbom) + + godoc-mcp: + type: mcp + command: godoc-mcp + env: + GOPATH: ${HOME}/go + GOMODCACHE: ${HOME}/go/pkg/mod + GOROOT: /snap/go/current + instruction: Go documentation lookup via godoc-mcp + + go-lsp: + type: lsp + command: gopls + file_types: [".go"] + instruction: Go language server for code intelligence + +# ============================================================ +# Agents +# ============================================================ agents: # root — execution loop coordinator @@ -17,18 +99,7 @@ agents: sub_agents: [executor, verifier] - # autonomous is safe because global ~/.config/cagent/config.yaml - # covers restrictions: deny rules for sudo*, rm -rf*, chmod*, etc. - safety: autonomous - - toolsets: - - type: filesystem - # filesystem access scoped to current repo; global deny rules - # (e.g. write to /etc/**, delete_path outside repo) are enforced - # at the user config level - allow_list: ["."] - - - type: shell + use_toolsets: [fs-scoped, shell-tool] # executor — runs speckit-implement executor: @@ -39,72 +110,7 @@ agents: skills: - speckit-implement - # autonomous is safe because global ~/.config/cagent/config.yaml - # covers restrictions: deny rules for sudo*, rm -rf*, chmod*, etc. - safety: autonomous - - toolsets: - - type: script - shell: - lint: - cmd: task lint - description: Run all linters (golangci-lint, etc.) - - format: - cmd: task format paths=${paths} - description: Format Go source code - args: - paths: - type: string - description: Target directory to format (e.g. pkg/foo) - - mock-gen: - cmd: task mock:generate - description: Generate Go mock files via mockgen - - doc-gen: - cmd: task doc:gen - description: Generate CLI reference documentation - - test-unit: - cmd: task test:unit paths=${paths} -- -focus=${focus} - description: Run unit tests with optional package paths and focus filter - args: - paths: - type: string - description: Package paths (e.g. ./pkg/...) - focus: - type: string - description: Ginkgo focus pattern for test selection - - test-e2e: - cmd: task test:e2e paths=${paths} labelFilter=${labelFilter} - description: Run e2e tests with optional package paths and label filter - args: - paths: - type: string - description: E2e test package paths (e.g. ./test/e2e/sbom/...) - labelFilter: - type: string - description: Ginkgo label filter for test selection (e.g. sbom) - - - type: filesystem - allow_list: ["."] - - - type: shell - - - type: mcp - command: godoc-mcp - env: - GOPATH: ${HOME}/go - GOMODCACHE: ${HOME}/go/pkg/mod - GOROOT: /snap/go/current - instruction: Go documentation lookup via godoc-mcp - - - type: lsp - command: gopls - file_types: [".go"] - instruction: Go language server for code intelligence + use_toolsets: [fs-scoped, shell-tool, script-tools, godoc-mcp, go-lsp] # verifier — runs speckit-converge verifier: @@ -115,11 +121,4 @@ agents: skills: - speckit-converge - # autonomous is safe because global ~/.config/cagent/config.yaml - # covers restrictions: deny rules for sudo*, rm -rf*, chmod*, etc. - safety: autonomous - - toolsets: - - type: filesystem - allow_list: ["."] - - type: shell + use_toolsets: [fs-scoped, shell-tool, script-tools, godoc-mcp, go-lsp] diff --git a/.cagent/speckit-execution-loop/instructions-root.md b/.cagent/speckit-execution-loop/instructions-root.md index f955996b5f..3b92af296c 100644 --- a/.cagent/speckit-execution-loop/instructions-root.md +++ b/.cagent/speckit-execution-loop/instructions-root.md @@ -1,29 +1,32 @@ # Root Agent — Execution Loop -You are the execution loop coordinator for spec-driven development in the delivery-kit (werf) project. Your role is to drive the implement → converge → check cycle by delegating to sub-agents. +You are the execution loop coordinator for spec-driven development in the delivery-kit (werf) project. Your role is to drive the implement → converge → check cycle by delegating to sub-agents. You never execute implementation or verification commands yourself — only orchestration tasks. ## Loop -1. Read `FEATURE_DIR` from `.specify/feature.json` using `jq -r '.feature_directory' .specify/feature.json`. - Let `TASKS_FILE = specs/${FEATURE_DIR}/tasks.md` - -2. Remember current line count: `wc -l < ${TASKS_FILE}` → save as PREV_COUNT - -3. Delegate implementation to `executor`: - - Use `transfer_task` with agent: `"executor"`, task: `"Run /speckit-implement"` +1. Delegate implementation to `executor`: + - On the first iteration: include any user-provided arguments in the task. + Use `transfer_task` with agent: `"executor"`, task: `"Run /speckit-implement ${user_input}"` + where `${user_input}` is the user's original message. + - On subsequent iterations: use `transfer_task` with agent: `"executor"`, task: `"Run /speckit-implement"` - Wait for the result -4. Delegate convergence check to `verifier`: +2. Read `FEATURE_DIR` from `.specify/feature.json`: + - `FEATURE_DIR=$(jq -r '.feature_directory' .specify/feature.json)` + - Let `TASKS_FILE = specs/${FEATURE_DIR}/tasks.md` + - Save current byte count: `PREV_BYTES=$(wc -c < ${TASKS_FILE})` + +3. Delegate convergence check to `verifier`: - Use `transfer_task` with agent: `"verifier"`, task: `"Run /speckit-converge"` - Wait for the result -5. Check current line count: `wc -l < ${TASKS_FILE}` → save as CURR_COUNT +4. Check current byte count: `CURR_BYTES=$(wc -c < ${TASKS_FILE})` -6. If CURR_COUNT != PREV_COUNT → go to step 2 +5. If `CURR_BYTES != PREV_BYTES` → go to step 1 -7. Otherwise → report completion with a summary of implemented work +6. Otherwise → report completion ## Important Rules - Never modify `spec.md`, `plan.md`, `tasks.md` or `feature.json` directly. -- If a sub-agent task fails or returns an error, report it and stop the loop. +- If a sub-agent task fails or returns an error, report it and stop the loop. \ No newline at end of file