diff --git a/CHANGELOG.md b/CHANGELOG.md index c566b5687..4607cc94e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,15 @@ # Changelog All notable changes to this project will be documented in this file. +## [2.5.13] - 2026-07-25 + +The Kiro IDE distribution now ships only surfaces Kiro IDE actually reads. Agents ship as Markdown, with the conductor as `.kiro/agents/aidlc.md` so it appears in the IDE's workspace agent selector; the Kiro CLI's agent-v1 JSON configs and `settings/cli.json` are no longer part of this tree, since the IDE reads neither. Delegated agents carry an IDE-native `permissions.rules` block instead of the CLI-only `disallowedTools` field. **Upgrade:** re-copy `dist/kiro-ide/.kiro/` into your project, then delete the `.kiro/agents/aidlc-*.json`, `.kiro/agents/aidlc.json`, and `.kiro/settings/cli.json` files a previous install left behind — a content-copy leaves them in place, and while the IDE ignores them, `--doctor` keeps checking for `settings/cli.json` as long as `agents/aidlc.json` is still there. Kiro CLI (`dist/kiro/`) is unchanged. + +* Kiro IDE agents ship as Markdown only: the 14 personas as `.kiro/agents/aidlc-*-agent.md` and the conductor as `.kiro/agents/aidlc.md` (the entry the IDE's workspace agent selector loads). The 15 agent-v1 JSON files and `settings/cli.json` are dropped from this distribution. +* Each delegation-target persona now carries a `permissions.rules` block (shell `bun .kiro/tools/aidlc-*`/`date -u *`, filesystem `aidlc/spaces/**`; the composer gets `.kiro/scopes/**` + the scope grid) alongside its existing `tools:` grant, and no longer carries `disallowedTools` — a Claude Code field the IDE does not recognize. The IDE has no `allowedCommands`/`allowedPaths` equivalent, so this capability/effect/match block is where a delegate's scoping lives. +* `/aidlc --doctor` accepts either `agents/aidlc.json` or `agents/aidlc.md` as the conductor agent's hook + permission wiring, and runs the `settings/cli.json` row only on a CLI install (one where `agents/aidlc.json` is present) — an IDE install no longer fails a check for a CLI-only file it does not ship. +* Docs updated for the IDE's real surfaces (`docs/guide/harnesses/kiro-ide.md`, `docs/reference/14-claude-features.md`). No command or flag changes; no breaking change for CI or scripts. + ## [2.5.11] - 2026-07-24 Intent Capture now keeps generated intent and stakeholder claims grounded in the user's description, confirmed answers, workflow-selected scope, or explicitly registered memory. Unsupported content is omitted, elicited, or surfaced as a human-owned assumption instead of being presented as fact. **Upgrade:** re-copy your `dist//` shell into the project so the updated stage, Product Lead reviewer contract, and `claim-sources` sensor are installed. diff --git a/README.md b/README.md index 1e4e7912a..893db6060 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ A native implementation of the **AI-DLC methodology** (AI-Driven Development Lif The methodology lives once, in a harness-neutral `core/`; each harness adds a thin surface that decides how it shows up on that harness. So you edit the methodology in one place, and every harness distribution is generated from it — no harness gets special treatment. (See [Repository layout](#repository-layout) for how the pieces fit together.) -![version](https://img.shields.io/badge/version-2.5.11-blue) +![version](https://img.shields.io/badge/version-2.5.13-blue) ![license](https://img.shields.io/badge/license-MIT--0-green) ![Kiro IDE](https://img.shields.io/badge/harness-Kiro%20IDE-orange) ![Kiro CLI](https://img.shields.io/badge/harness-Kiro%20CLI-orange) @@ -128,7 +128,7 @@ cp dist/kiro-ide/AGENTS.md your-project/AGENTS.md # merge if you already have The `aidlc/` shell ships the pre-built `aidlc/spaces/default/memory/` method tree the engine reads; `/aidlc --doctor` fails its "workspace shell ready" check without it. -Open `your-project/` in Kiro IDE. The `/aidlc` command loads the shipped conductor skill (the bundled `.kiro/settings/cli.json` is a Kiro CLI-only compatibility surface — the IDE ignores it and does not select a default agent from it). The install registers the framework hooks in both formats: `.kiro/hooks/aidlc-*.json` (v2 schema for IDE >= 1.0) and `.kiro/hooks/aidlc-*.kiro.hook` (legacy format for pre-1.0 IDEs). In the chat panel, run `/aidlc --doctor` to verify, then `/aidlc ` to start. +Open `your-project/` in Kiro IDE. The `/aidlc` command loads the shipped conductor skill; the IDE activates its agent from the workspace agent selector, so this distribution ships no `settings/cli.json` (that file is the Kiro CLI's default-agent activation surface and stays in `dist/kiro/`). The install registers the framework hooks in both formats: `.kiro/hooks/aidlc-*.json` (v2 schema for IDE >= 1.0) and `.kiro/hooks/aidlc-*.kiro.hook` (legacy format for pre-1.0 IDEs). In the chat panel, run `/aidlc --doctor` to verify, then `/aidlc ` to start. > [!NOTE] > AI-DLC on Kiro works best with **Claude Opus 4.8**, which requires a **paid Kiro plan**. On weaker models the conductor may skip optional stage steps (reviewer pass, learnings ritual) or rush approval gates. diff --git a/core/tools/aidlc-lib.ts b/core/tools/aidlc-lib.ts index 3906d2cec..0a81d8549 100644 --- a/core/tools/aidlc-lib.ts +++ b/core/tools/aidlc-lib.ts @@ -3926,7 +3926,14 @@ export function loadAgents(): AgentMetadata[] { const dir = agentsDir(); const slugToFile = new Map(); const agents: AgentMetadata[] = []; - const files = readdirSync(dir).filter((f) => f.endsWith(".md")).sort(); + // aidlc.md is the conductor MAIN (IDE custom-agent selector entry), not a + // stage lead/support agent — it carries no name/display_name/examples and + // must not enter the domain-agent roster (it would fail schema validation + // and pollute knownAgents used for stage lead_agent checks). Exclude it. + // No-op for harnesses that ship no aidlc.md (every tree but the Kiro IDE). + const files = readdirSync(dir) + .filter((f) => f.endsWith(".md") && f !== "aidlc.md") + .sort(); for (const f of files) { const filePath = join(dir, f); const agent = parseAgentFrontmatter(filePath); diff --git a/core/tools/aidlc-utility.ts b/core/tools/aidlc-utility.ts index 9b257f5ab..79cf8358f 100644 --- a/core/tools/aidlc-utility.ts +++ b/core/tools/aidlc-utility.ts @@ -1239,18 +1239,29 @@ function handleDoctor(projectDir: string, flags: Record = {}): v // permissions live there) plus settings/cli.json (activation). Codex CLI: // config.toml + hooks.json (the hook wiring) + rules/default.rules (permissions). if (harness === ".kiro") { - const agentPath = join(projectDir, harness, "agents", "aidlc.json"); + // The conductor agent config carries the hook + permission wiring. Kiro CLI + // ships it as agents/aidlc.json; Kiro IDE reads the Markdown agent format + // (agents/aidlc.md) instead — either satisfies the wiring requirement, so + // accept whichever is present. + const jsonAgentPath = join(projectDir, harness, "agents", "aidlc.json"); + const mdAgentPath = join(projectDir, harness, "agents", "aidlc.md"); results.push({ - pass: existsSync(agentPath), - label: "agents/aidlc.json present (hook + permission wiring)", - fix: "copy from `dist/kiro/.kiro/agents/aidlc.json`", - }); - const cliSettingsPath = join(projectDir, harness, "settings", "cli.json"); - results.push({ - pass: existsSync(cliSettingsPath), - label: "settings/cli.json present (workspace default-agent activation)", - fix: "copy from `dist/kiro/.kiro/settings/cli.json` (or use `kiro-cli chat --agent aidlc`)", + pass: existsSync(jsonAgentPath) || existsSync(mdAgentPath), + label: "agents/aidlc.{json,md} present (hook + permission wiring)", + fix: "copy from `dist/kiro/.kiro/agents/aidlc.json` (Kiro CLI) or `dist/kiro-ide/.kiro/agents/aidlc.md` (Kiro IDE)", }); + // settings/cli.json activates the default agent for Kiro CLI only. Kiro IDE + // activates via the agent selector and ships no settings file, so this check + // applies solely to a CLI install (aidlc.json present). Skip it for an IDE + // install (aidlc.md present, no aidlc.json). + if (existsSync(jsonAgentPath)) { + const cliSettingsPath = join(projectDir, harness, "settings", "cli.json"); + results.push({ + pass: existsSync(cliSettingsPath), + label: "settings/cli.json present (workspace default-agent activation)", + fix: "copy from `dist/kiro/.kiro/settings/cli.json` (or use `kiro-cli chat --agent aidlc`)", + }); + } } else if (harness === ".codex") { for (const [file, what, from] of [ ["config.toml", "model/provider/sandbox config", "dist/codex/.codex/config.toml"], diff --git a/core/tools/aidlc-version.ts b/core/tools/aidlc-version.ts index 0695010b6..49f646dce 100644 --- a/core/tools/aidlc-version.ts +++ b/core/tools/aidlc-version.ts @@ -1,4 +1,4 @@ // Hand-edited single source of truth for the AIDLC framework version. // Bumped in the same commit that adds the matching ## [N.N.N] heading // to CHANGELOG.md. Pinned by tests/unit/t68-version-changelog-sync.test.ts. -export const AIDLC_VERSION = "2.5.11"; +export const AIDLC_VERSION = "2.5.13"; diff --git a/dist/claude/.claude/tools/aidlc-lib.ts b/dist/claude/.claude/tools/aidlc-lib.ts index 3906d2cec..0a81d8549 100644 --- a/dist/claude/.claude/tools/aidlc-lib.ts +++ b/dist/claude/.claude/tools/aidlc-lib.ts @@ -3926,7 +3926,14 @@ export function loadAgents(): AgentMetadata[] { const dir = agentsDir(); const slugToFile = new Map(); const agents: AgentMetadata[] = []; - const files = readdirSync(dir).filter((f) => f.endsWith(".md")).sort(); + // aidlc.md is the conductor MAIN (IDE custom-agent selector entry), not a + // stage lead/support agent — it carries no name/display_name/examples and + // must not enter the domain-agent roster (it would fail schema validation + // and pollute knownAgents used for stage lead_agent checks). Exclude it. + // No-op for harnesses that ship no aidlc.md (every tree but the Kiro IDE). + const files = readdirSync(dir) + .filter((f) => f.endsWith(".md") && f !== "aidlc.md") + .sort(); for (const f of files) { const filePath = join(dir, f); const agent = parseAgentFrontmatter(filePath); diff --git a/dist/claude/.claude/tools/aidlc-utility.ts b/dist/claude/.claude/tools/aidlc-utility.ts index 9b257f5ab..79cf8358f 100644 --- a/dist/claude/.claude/tools/aidlc-utility.ts +++ b/dist/claude/.claude/tools/aidlc-utility.ts @@ -1239,18 +1239,29 @@ function handleDoctor(projectDir: string, flags: Record = {}): v // permissions live there) plus settings/cli.json (activation). Codex CLI: // config.toml + hooks.json (the hook wiring) + rules/default.rules (permissions). if (harness === ".kiro") { - const agentPath = join(projectDir, harness, "agents", "aidlc.json"); + // The conductor agent config carries the hook + permission wiring. Kiro CLI + // ships it as agents/aidlc.json; Kiro IDE reads the Markdown agent format + // (agents/aidlc.md) instead — either satisfies the wiring requirement, so + // accept whichever is present. + const jsonAgentPath = join(projectDir, harness, "agents", "aidlc.json"); + const mdAgentPath = join(projectDir, harness, "agents", "aidlc.md"); results.push({ - pass: existsSync(agentPath), - label: "agents/aidlc.json present (hook + permission wiring)", - fix: "copy from `dist/kiro/.kiro/agents/aidlc.json`", - }); - const cliSettingsPath = join(projectDir, harness, "settings", "cli.json"); - results.push({ - pass: existsSync(cliSettingsPath), - label: "settings/cli.json present (workspace default-agent activation)", - fix: "copy from `dist/kiro/.kiro/settings/cli.json` (or use `kiro-cli chat --agent aidlc`)", + pass: existsSync(jsonAgentPath) || existsSync(mdAgentPath), + label: "agents/aidlc.{json,md} present (hook + permission wiring)", + fix: "copy from `dist/kiro/.kiro/agents/aidlc.json` (Kiro CLI) or `dist/kiro-ide/.kiro/agents/aidlc.md` (Kiro IDE)", }); + // settings/cli.json activates the default agent for Kiro CLI only. Kiro IDE + // activates via the agent selector and ships no settings file, so this check + // applies solely to a CLI install (aidlc.json present). Skip it for an IDE + // install (aidlc.md present, no aidlc.json). + if (existsSync(jsonAgentPath)) { + const cliSettingsPath = join(projectDir, harness, "settings", "cli.json"); + results.push({ + pass: existsSync(cliSettingsPath), + label: "settings/cli.json present (workspace default-agent activation)", + fix: "copy from `dist/kiro/.kiro/settings/cli.json` (or use `kiro-cli chat --agent aidlc`)", + }); + } } else if (harness === ".codex") { for (const [file, what, from] of [ ["config.toml", "model/provider/sandbox config", "dist/codex/.codex/config.toml"], diff --git a/dist/claude/.claude/tools/aidlc-version.ts b/dist/claude/.claude/tools/aidlc-version.ts index 0695010b6..49f646dce 100644 --- a/dist/claude/.claude/tools/aidlc-version.ts +++ b/dist/claude/.claude/tools/aidlc-version.ts @@ -1,4 +1,4 @@ // Hand-edited single source of truth for the AIDLC framework version. // Bumped in the same commit that adds the matching ## [N.N.N] heading // to CHANGELOG.md. Pinned by tests/unit/t68-version-changelog-sync.test.ts. -export const AIDLC_VERSION = "2.5.11"; +export const AIDLC_VERSION = "2.5.13"; diff --git a/dist/codex/.codex/tools/aidlc-lib.ts b/dist/codex/.codex/tools/aidlc-lib.ts index 3906d2cec..0a81d8549 100644 --- a/dist/codex/.codex/tools/aidlc-lib.ts +++ b/dist/codex/.codex/tools/aidlc-lib.ts @@ -3926,7 +3926,14 @@ export function loadAgents(): AgentMetadata[] { const dir = agentsDir(); const slugToFile = new Map(); const agents: AgentMetadata[] = []; - const files = readdirSync(dir).filter((f) => f.endsWith(".md")).sort(); + // aidlc.md is the conductor MAIN (IDE custom-agent selector entry), not a + // stage lead/support agent — it carries no name/display_name/examples and + // must not enter the domain-agent roster (it would fail schema validation + // and pollute knownAgents used for stage lead_agent checks). Exclude it. + // No-op for harnesses that ship no aidlc.md (every tree but the Kiro IDE). + const files = readdirSync(dir) + .filter((f) => f.endsWith(".md") && f !== "aidlc.md") + .sort(); for (const f of files) { const filePath = join(dir, f); const agent = parseAgentFrontmatter(filePath); diff --git a/dist/codex/.codex/tools/aidlc-utility.ts b/dist/codex/.codex/tools/aidlc-utility.ts index 9b257f5ab..79cf8358f 100644 --- a/dist/codex/.codex/tools/aidlc-utility.ts +++ b/dist/codex/.codex/tools/aidlc-utility.ts @@ -1239,18 +1239,29 @@ function handleDoctor(projectDir: string, flags: Record = {}): v // permissions live there) plus settings/cli.json (activation). Codex CLI: // config.toml + hooks.json (the hook wiring) + rules/default.rules (permissions). if (harness === ".kiro") { - const agentPath = join(projectDir, harness, "agents", "aidlc.json"); + // The conductor agent config carries the hook + permission wiring. Kiro CLI + // ships it as agents/aidlc.json; Kiro IDE reads the Markdown agent format + // (agents/aidlc.md) instead — either satisfies the wiring requirement, so + // accept whichever is present. + const jsonAgentPath = join(projectDir, harness, "agents", "aidlc.json"); + const mdAgentPath = join(projectDir, harness, "agents", "aidlc.md"); results.push({ - pass: existsSync(agentPath), - label: "agents/aidlc.json present (hook + permission wiring)", - fix: "copy from `dist/kiro/.kiro/agents/aidlc.json`", - }); - const cliSettingsPath = join(projectDir, harness, "settings", "cli.json"); - results.push({ - pass: existsSync(cliSettingsPath), - label: "settings/cli.json present (workspace default-agent activation)", - fix: "copy from `dist/kiro/.kiro/settings/cli.json` (or use `kiro-cli chat --agent aidlc`)", + pass: existsSync(jsonAgentPath) || existsSync(mdAgentPath), + label: "agents/aidlc.{json,md} present (hook + permission wiring)", + fix: "copy from `dist/kiro/.kiro/agents/aidlc.json` (Kiro CLI) or `dist/kiro-ide/.kiro/agents/aidlc.md` (Kiro IDE)", }); + // settings/cli.json activates the default agent for Kiro CLI only. Kiro IDE + // activates via the agent selector and ships no settings file, so this check + // applies solely to a CLI install (aidlc.json present). Skip it for an IDE + // install (aidlc.md present, no aidlc.json). + if (existsSync(jsonAgentPath)) { + const cliSettingsPath = join(projectDir, harness, "settings", "cli.json"); + results.push({ + pass: existsSync(cliSettingsPath), + label: "settings/cli.json present (workspace default-agent activation)", + fix: "copy from `dist/kiro/.kiro/settings/cli.json` (or use `kiro-cli chat --agent aidlc`)", + }); + } } else if (harness === ".codex") { for (const [file, what, from] of [ ["config.toml", "model/provider/sandbox config", "dist/codex/.codex/config.toml"], diff --git a/dist/codex/.codex/tools/aidlc-version.ts b/dist/codex/.codex/tools/aidlc-version.ts index 0695010b6..49f646dce 100644 --- a/dist/codex/.codex/tools/aidlc-version.ts +++ b/dist/codex/.codex/tools/aidlc-version.ts @@ -1,4 +1,4 @@ // Hand-edited single source of truth for the AIDLC framework version. // Bumped in the same commit that adds the matching ## [N.N.N] heading // to CHANGELOG.md. Pinned by tests/unit/t68-version-changelog-sync.test.ts. -export const AIDLC_VERSION = "2.5.11"; +export const AIDLC_VERSION = "2.5.13"; diff --git a/dist/kiro-ide/.kiro/agents/aidlc-architect-agent.json b/dist/kiro-ide/.kiro/agents/aidlc-architect-agent.json deleted file mode 100644 index db95b4732..000000000 --- a/dist/kiro-ide/.kiro/agents/aidlc-architect-agent.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/aws/amazon-q-developer-cli/refs/heads/main/schemas/agent-v1.json", - "name": "aidlc-architect-agent", - "description": "AI-DLC Architect Agent — delegation target for the reverse-engineering (2.1) synthesis step. Use for delegated architecture-analysis tasks.", - "prompt": "file://aidlc-architect-agent.md", - "tools": [ - "fs_read", - "fs_write", - "execute_bash", - "thinking" - ], - "allowedTools": [ - "fs_read", - "thinking" - ], - "toolsSettings": { - "execute_bash": { - "allowedCommands": [ - "bun \\.kiro/tools/.*", - "date -u .*" - ] - }, - "fs_write": { - "allowedPaths": [ - "aidlc/spaces/**" - ] - } - }, - "resources": [ - "file://.kiro/agents/aidlc-architect-agent.md", - "file://.kiro/knowledge/aidlc-architect-agent/*.md", - "file://.kiro/knowledge/aidlc-shared/*.md", - "file://aidlc/spaces/default/memory/**/*.md" - ], - "hooks": {} -} diff --git a/dist/kiro-ide/.kiro/agents/aidlc-architect-agent.md b/dist/kiro-ide/.kiro/agents/aidlc-architect-agent.md index 134e29e15..ff9639088 100644 --- a/dist/kiro-ide/.kiro/agents/aidlc-architect-agent.md +++ b/dist/kiro-ide/.kiro/agents/aidlc-architect-agent.md @@ -8,8 +8,18 @@ description: > Solutions architect responsible for application design, domain modelling, NFR patterns, and component decomposition. Leads Feasibility, Application Design, Units Generation, Functional Design, NFR Requirements, and NFR Design stages, and serves as the dispatched final link of the Reverse Engineering pipeline. -disallowedTools: Task tools: ["read", "write", "shell"] +permissions: + rules: + - capability: shell + effect: allow + match: + - "bun .kiro/tools/aidlc-*" + - "date -u *" + - capability: filesystem + effect: allow + match: + - "aidlc/spaces/**" --- **IMPORTANT: Do NOT use the Task tool. You operate as a delegated agent and must not spawn sub-agents.** diff --git a/dist/kiro-ide/.kiro/agents/aidlc-architecture-reviewer-agent.json b/dist/kiro-ide/.kiro/agents/aidlc-architecture-reviewer-agent.json deleted file mode 100644 index d737e99b7..000000000 --- a/dist/kiro-ide/.kiro/agents/aidlc-architecture-reviewer-agent.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/aws/amazon-q-developer-cli/refs/heads/main/schemas/agent-v1.json", - "name": "aidlc-architecture-reviewer-agent", - "description": "AI-DLC Architecture Reviewer — delegation target for reviewing design artifacts for soundness and implementability.", - "prompt": "file://aidlc-architecture-reviewer-agent.md", - "tools": [ - "fs_read", - "fs_write", - "execute_bash", - "thinking" - ], - "allowedTools": [ - "fs_read", - "fs_write", - "thinking" - ], - "toolsSettings": { - "execute_bash": { - "allowedCommands": [ - "bun \\.kiro/tools/.*", - "date -u .*" - ] - }, - "fs_write": { - "allowedPaths": [ - "aidlc/spaces/**" - ] - } - }, - "resources": [ - "file://.kiro/agents/aidlc-architecture-reviewer-agent.md", - "file://.kiro/knowledge/aidlc-architecture-reviewer-agent/*.md", - "file://.kiro/knowledge/aidlc-shared/*.md", - "file://aidlc/spaces/default/memory/**/*.md" - ], - "hooks": {} -} diff --git a/dist/kiro-ide/.kiro/agents/aidlc-architecture-reviewer-agent.md b/dist/kiro-ide/.kiro/agents/aidlc-architecture-reviewer-agent.md index ee2d2e8a4..49999fdab 100644 --- a/dist/kiro-ide/.kiro/agents/aidlc-architecture-reviewer-agent.md +++ b/dist/kiro-ide/.kiro/agents/aidlc-architecture-reviewer-agent.md @@ -3,8 +3,18 @@ name: aidlc-architecture-reviewer-agent display_name: Architecture Reviewer description: > Senior solutions architect who reviews technical design artifacts for soundness, implementability, and coherence. Finds broken cross-references, hidden dependencies, unachievable quality targets, and designs that won't survive contact with reality. -disallowedTools: Task tools: ["read", "write", "shell"] +permissions: + rules: + - capability: shell + effect: allow + match: + - "bun .kiro/tools/aidlc-*" + - "date -u *" + - capability: filesystem + effect: allow + match: + - "aidlc/spaces/**" --- **IMPORTANT: Do NOT use the Task tool. You operate as a delegated reviewer and must not spawn sub-agents.** diff --git a/dist/kiro-ide/.kiro/agents/aidlc-aws-platform-agent.json b/dist/kiro-ide/.kiro/agents/aidlc-aws-platform-agent.json deleted file mode 100644 index 91b3d586c..000000000 --- a/dist/kiro-ide/.kiro/agents/aidlc-aws-platform-agent.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/aws/amazon-q-developer-cli/refs/heads/main/schemas/agent-v1.json", - "name": "aidlc-aws-platform-agent", - "description": "AI-DLC AWS Platform Agent - delegation target for ensemble stages (AWS service selection, infrastructure, platform perspective).", - "prompt": "file://aidlc-aws-platform-agent.md", - "tools": [ - "fs_read", - "fs_write", - "execute_bash", - "thinking" - ], - "allowedTools": [ - "fs_read", - "thinking" - ], - "toolsSettings": { - "execute_bash": { - "allowedCommands": [ - "bun \\.kiro/tools/.*", - "date -u .*" - ] - }, - "fs_write": { - "allowedPaths": [ - "aidlc/spaces/**" - ] - } - }, - "resources": [ - "file://.kiro/agents/aidlc-aws-platform-agent.md", - "file://.kiro/knowledge/aidlc-aws-platform-agent/*.md", - "file://.kiro/knowledge/aidlc-shared/*.md", - "file://aidlc/spaces/default/memory/**/*.md" - ], - "hooks": {} -} diff --git a/dist/kiro-ide/.kiro/agents/aidlc-aws-platform-agent.md b/dist/kiro-ide/.kiro/agents/aidlc-aws-platform-agent.md index 19c990498..052f41e1c 100644 --- a/dist/kiro-ide/.kiro/agents/aidlc-aws-platform-agent.md +++ b/dist/kiro-ide/.kiro/agents/aidlc-aws-platform-agent.md @@ -8,8 +8,18 @@ description: > AWS solutions architect responsible for infrastructure design, environment provisioning, and cloud-native architecture. Leads Infrastructure Design and Environment Provisioning stages. Supports Feasibility, Application Design, NFR Design, and Feedback & Optimization. -disallowedTools: Task tools: ["read", "write", "shell"] +permissions: + rules: + - capability: shell + effect: allow + match: + - "bun .kiro/tools/aidlc-*" + - "date -u *" + - capability: filesystem + effect: allow + match: + - "aidlc/spaces/**" --- **IMPORTANT: Do NOT use the Task tool. You operate as a delegated agent and must not spawn sub-agents.** diff --git a/dist/kiro-ide/.kiro/agents/aidlc-compliance-agent.json b/dist/kiro-ide/.kiro/agents/aidlc-compliance-agent.json deleted file mode 100644 index 208eb51af..000000000 --- a/dist/kiro-ide/.kiro/agents/aidlc-compliance-agent.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/aws/amazon-q-developer-cli/refs/heads/main/schemas/agent-v1.json", - "name": "aidlc-compliance-agent", - "description": "AI-DLC Compliance Agent - delegation target for ensemble stages (regulatory, data-residency, audit perspective).", - "prompt": "file://aidlc-compliance-agent.md", - "tools": [ - "fs_read", - "fs_write", - "execute_bash", - "thinking" - ], - "allowedTools": [ - "fs_read", - "thinking" - ], - "toolsSettings": { - "execute_bash": { - "allowedCommands": [ - "bun \\.kiro/tools/.*", - "date -u .*" - ] - }, - "fs_write": { - "allowedPaths": [ - "aidlc/spaces/**" - ] - } - }, - "resources": [ - "file://.kiro/agents/aidlc-compliance-agent.md", - "file://.kiro/knowledge/aidlc-compliance-agent/*.md", - "file://.kiro/knowledge/aidlc-shared/*.md", - "file://aidlc/spaces/default/memory/**/*.md" - ], - "hooks": {} -} diff --git a/dist/kiro-ide/.kiro/agents/aidlc-compliance-agent.md b/dist/kiro-ide/.kiro/agents/aidlc-compliance-agent.md index 2baabaf5a..9545e4251 100644 --- a/dist/kiro-ide/.kiro/agents/aidlc-compliance-agent.md +++ b/dist/kiro-ide/.kiro/agents/aidlc-compliance-agent.md @@ -7,8 +7,18 @@ examples: description: > GRC analyst and regulatory specialist responsible for compliance mapping, data classification, and risk assessment. Support-only agent for Feasibility & Constraint Analysis and cross-cutting compliance validation. -disallowedTools: Task tools: ["read", "write", "shell"] +permissions: + rules: + - capability: shell + effect: allow + match: + - "bun .kiro/tools/aidlc-*" + - "date -u *" + - capability: filesystem + effect: allow + match: + - "aidlc/spaces/**" --- **IMPORTANT: Do NOT use the Task tool. You operate as a delegated agent and must not spawn sub-agents.** diff --git a/dist/kiro-ide/.kiro/agents/aidlc-composer-agent.json b/dist/kiro-ide/.kiro/agents/aidlc-composer-agent.json deleted file mode 100644 index a98f7970d..000000000 --- a/dist/kiro-ide/.kiro/agents/aidlc-composer-agent.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/aws/amazon-q-developer-cli/refs/heads/main/schemas/agent-v1.json", - "name": "aidlc-composer-agent", - "description": "AI-DLC Composer Agent - delegation target for composing a workflow plan (front, report, or in-flight). Proposes the EXECUTE/SKIP grid; after human approval writes the composed scope data.", - "prompt": "file://aidlc-composer-agent.md", - "tools": [ - "fs_read", - "fs_write", - "execute_bash", - "thinking" - ], - "allowedTools": [ - "fs_read", - "thinking" - ], - "toolsSettings": { - "execute_bash": { - "allowedCommands": [ - "bun \\.kiro/tools/.*", - "date -u .*" - ] - }, - "fs_write": { - "allowedPaths": [ - ".kiro/scopes/**", - ".kiro/tools/data/scope-grid.json" - ] - } - }, - "resources": [ - "file://.kiro/agents/aidlc-composer-agent.md", - "file://.kiro/scopes/*.md", - "file://.kiro/knowledge/aidlc-shared/*.md", - "file://aidlc/spaces/default/memory/**/*.md" - ], - "hooks": {} -} diff --git a/dist/kiro-ide/.kiro/agents/aidlc-composer-agent.md b/dist/kiro-ide/.kiro/agents/aidlc-composer-agent.md index 2a8c85235..484a5eae7 100644 --- a/dist/kiro-ide/.kiro/agents/aidlc-composer-agent.md +++ b/dist/kiro-ide/.kiro/agents/aidlc-composer-agent.md @@ -11,8 +11,19 @@ description: > indexed; only falls back to bounded workspace analysis when CodeKB is absent or not ready. Dispatched by the /aidlc orchestrator; never invoked directly by a stage. -disallowedTools: Task tools: ["read", "write", "shell"] +permissions: + rules: + - capability: shell + effect: allow + match: + - "bun .kiro/tools/aidlc-*" + - "date -u *" + - capability: filesystem + effect: allow + match: + - ".kiro/scopes/**" + - ".kiro/tools/data/scope-grid.json" --- **IMPORTANT: Do NOT use the Task tool. You operate as a delegated agent and must not spawn sub-agents.** diff --git a/dist/kiro-ide/.kiro/agents/aidlc-delivery-agent.json b/dist/kiro-ide/.kiro/agents/aidlc-delivery-agent.json deleted file mode 100644 index d193ddaed..000000000 --- a/dist/kiro-ide/.kiro/agents/aidlc-delivery-agent.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/aws/amazon-q-developer-cli/refs/heads/main/schemas/agent-v1.json", - "name": "aidlc-delivery-agent", - "description": "AI-DLC Delivery Agent - delegation target for ensemble stages (delivery planning, sequencing, approval-handoff perspective).", - "prompt": "file://aidlc-delivery-agent.md", - "tools": [ - "fs_read", - "fs_write", - "execute_bash", - "thinking" - ], - "allowedTools": [ - "fs_read", - "thinking" - ], - "toolsSettings": { - "execute_bash": { - "allowedCommands": [ - "bun \\.kiro/tools/.*", - "date -u .*" - ] - }, - "fs_write": { - "allowedPaths": [ - "aidlc/spaces/**" - ] - } - }, - "resources": [ - "file://.kiro/agents/aidlc-delivery-agent.md", - "file://.kiro/knowledge/aidlc-delivery-agent/*.md", - "file://.kiro/knowledge/aidlc-shared/*.md", - "file://aidlc/spaces/default/memory/**/*.md" - ], - "hooks": {} -} diff --git a/dist/kiro-ide/.kiro/agents/aidlc-delivery-agent.md b/dist/kiro-ide/.kiro/agents/aidlc-delivery-agent.md index e8b41e904..04318e022 100644 --- a/dist/kiro-ide/.kiro/agents/aidlc-delivery-agent.md +++ b/dist/kiro-ide/.kiro/agents/aidlc-delivery-agent.md @@ -8,8 +8,18 @@ description: > Engineering manager responsible for team formation, Bolt sequencing, and phase handoffs. Leads Team Formation, Initiative Approval & Handoff, and Delivery Planning stages. Supports Scope Definition and Units Generation. -disallowedTools: Task tools: ["read", "write", "shell"] +permissions: + rules: + - capability: shell + effect: allow + match: + - "bun .kiro/tools/aidlc-*" + - "date -u *" + - capability: filesystem + effect: allow + match: + - "aidlc/spaces/**" --- **IMPORTANT: Do NOT use the Task tool. You operate as a delegated agent and must not spawn sub-agents.** diff --git a/dist/kiro-ide/.kiro/agents/aidlc-design-agent.json b/dist/kiro-ide/.kiro/agents/aidlc-design-agent.json deleted file mode 100644 index 42abfd443..000000000 --- a/dist/kiro-ide/.kiro/agents/aidlc-design-agent.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/aws/amazon-q-developer-cli/refs/heads/main/schemas/agent-v1.json", - "name": "aidlc-design-agent", - "description": "AI-DLC Design Agent - delegation target for ensemble stages (UX/UI perspective: mockups, personas, user experience).", - "prompt": "file://aidlc-design-agent.md", - "tools": [ - "fs_read", - "fs_write", - "execute_bash", - "thinking" - ], - "allowedTools": [ - "fs_read", - "thinking" - ], - "toolsSettings": { - "execute_bash": { - "allowedCommands": [ - "bun \\.kiro/tools/.*", - "date -u .*" - ] - }, - "fs_write": { - "allowedPaths": [ - "aidlc/spaces/**" - ] - } - }, - "resources": [ - "file://.kiro/agents/aidlc-design-agent.md", - "file://.kiro/knowledge/aidlc-design-agent/*.md", - "file://.kiro/knowledge/aidlc-shared/*.md", - "file://aidlc/spaces/default/memory/**/*.md" - ], - "hooks": {} -} diff --git a/dist/kiro-ide/.kiro/agents/aidlc-design-agent.md b/dist/kiro-ide/.kiro/agents/aidlc-design-agent.md index 50089fbf4..7eef8d21e 100644 --- a/dist/kiro-ide/.kiro/agents/aidlc-design-agent.md +++ b/dist/kiro-ide/.kiro/agents/aidlc-design-agent.md @@ -8,8 +8,18 @@ description: > UX/UI designer responsible for wireframing, interaction design, accessibility, and design system compliance. Leads Rough Mockups and Refined Mockups stages. Supports Application Design, and serves as a dispatched collaborator in the User Stories mob ensemble. -disallowedTools: Task tools: ["read", "write", "shell"] +permissions: + rules: + - capability: shell + effect: allow + match: + - "bun .kiro/tools/aidlc-*" + - "date -u *" + - capability: filesystem + effect: allow + match: + - "aidlc/spaces/**" --- **IMPORTANT: Do NOT use the Task tool. You operate as a delegated agent and must not spawn sub-agents.** diff --git a/dist/kiro-ide/.kiro/agents/aidlc-developer-agent.json b/dist/kiro-ide/.kiro/agents/aidlc-developer-agent.json deleted file mode 100644 index 229dd972c..000000000 --- a/dist/kiro-ide/.kiro/agents/aidlc-developer-agent.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/aws/amazon-q-developer-cli/refs/heads/main/schemas/agent-v1.json", - "name": "aidlc-developer-agent", - "description": "AI-DLC Developer Agent - delegation target for reverse-engineering (2.1), user-stories mob collaboration (2.4), code-generation (3.5), and swarm units. Use for delegated implementation tasks.", - "prompt": "file://aidlc-developer-agent.md", - "tools": [ - "fs_read", - "fs_write", - "execute_bash", - "thinking" - ], - "allowedTools": [ - "fs_read", - "thinking" - ], - "toolsSettings": { - "execute_bash": { - "allowedCommands": [ - "bun \\.kiro/tools/.*", - "date -u .*" - ] - }, - "fs_write": { - "allowedPaths": [ - "aidlc/spaces/**" - ] - } - }, - "resources": [ - "file://.kiro/agents/aidlc-developer-agent.md", - "file://.kiro/knowledge/aidlc-developer-agent/*.md", - "file://.kiro/knowledge/aidlc-shared/*.md", - "file://aidlc/spaces/default/memory/**/*.md" - ], - "hooks": {} -} diff --git a/dist/kiro-ide/.kiro/agents/aidlc-developer-agent.md b/dist/kiro-ide/.kiro/agents/aidlc-developer-agent.md index 50ef49fea..62f30d85b 100644 --- a/dist/kiro-ide/.kiro/agents/aidlc-developer-agent.md +++ b/dist/kiro-ide/.kiro/agents/aidlc-developer-agent.md @@ -8,8 +8,18 @@ description: > Senior developer responsible for code generation, reverse engineering, and data modelling. Leads the Reverse Engineering code scan and Code Generation, and serves as a dispatched collaborator in the Practices Discovery hub-and-spoke and User Stories mob ensembles. -disallowedTools: Task tools: ["read", "write", "shell"] +permissions: + rules: + - capability: shell + effect: allow + match: + - "bun .kiro/tools/aidlc-*" + - "date -u *" + - capability: filesystem + effect: allow + match: + - "aidlc/spaces/**" --- **IMPORTANT: Do NOT use the Task tool. You operate as a delegated agent and must not spawn sub-agents.** diff --git a/dist/kiro-ide/.kiro/agents/aidlc-devsecops-agent.json b/dist/kiro-ide/.kiro/agents/aidlc-devsecops-agent.json deleted file mode 100644 index b223e66d0..000000000 --- a/dist/kiro-ide/.kiro/agents/aidlc-devsecops-agent.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/aws/amazon-q-developer-cli/refs/heads/main/schemas/agent-v1.json", - "name": "aidlc-devsecops-agent", - "description": "AI-DLC DevSecOps Agent - delegation target for ensemble stages (security hardening, secrets, supply-chain perspective).", - "prompt": "file://aidlc-devsecops-agent.md", - "tools": [ - "fs_read", - "fs_write", - "execute_bash", - "thinking" - ], - "allowedTools": [ - "fs_read", - "thinking" - ], - "toolsSettings": { - "execute_bash": { - "allowedCommands": [ - "bun \\.kiro/tools/.*", - "date -u .*" - ] - }, - "fs_write": { - "allowedPaths": [ - "aidlc/spaces/**" - ] - } - }, - "resources": [ - "file://.kiro/agents/aidlc-devsecops-agent.md", - "file://.kiro/knowledge/aidlc-devsecops-agent/*.md", - "file://.kiro/knowledge/aidlc-shared/*.md", - "file://aidlc/spaces/default/memory/**/*.md" - ], - "hooks": {} -} diff --git a/dist/kiro-ide/.kiro/agents/aidlc-devsecops-agent.md b/dist/kiro-ide/.kiro/agents/aidlc-devsecops-agent.md index 7762327f1..a725e5853 100644 --- a/dist/kiro-ide/.kiro/agents/aidlc-devsecops-agent.md +++ b/dist/kiro-ide/.kiro/agents/aidlc-devsecops-agent.md @@ -8,8 +8,18 @@ description: > Security engineer and DevSecOps specialist responsible for threat modelling, security requirements, secure design review, and security pipeline integration. Supports NFR Requirements, Infrastructure Design, Build and Test, and Environment Provisioning, and serves as a dispatched collaborator in the Practices Discovery hub-and-spoke ensemble. -disallowedTools: Task tools: ["read", "write", "shell"] +permissions: + rules: + - capability: shell + effect: allow + match: + - "bun .kiro/tools/aidlc-*" + - "date -u *" + - capability: filesystem + effect: allow + match: + - "aidlc/spaces/**" --- **IMPORTANT: Do NOT use the Task tool. You operate as a delegated agent and must not spawn sub-agents.** diff --git a/dist/kiro-ide/.kiro/agents/aidlc-operations-agent.json b/dist/kiro-ide/.kiro/agents/aidlc-operations-agent.json deleted file mode 100644 index 79ac8a07e..000000000 --- a/dist/kiro-ide/.kiro/agents/aidlc-operations-agent.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/aws/amazon-q-developer-cli/refs/heads/main/schemas/agent-v1.json", - "name": "aidlc-operations-agent", - "description": "AI-DLC Operations Agent - delegation target for ensemble stages (observability, incident response, operations perspective).", - "prompt": "file://aidlc-operations-agent.md", - "tools": [ - "fs_read", - "fs_write", - "execute_bash", - "thinking" - ], - "allowedTools": [ - "fs_read", - "thinking" - ], - "toolsSettings": { - "execute_bash": { - "allowedCommands": [ - "bun \\.kiro/tools/.*", - "date -u .*" - ] - }, - "fs_write": { - "allowedPaths": [ - "aidlc/spaces/**" - ] - } - }, - "resources": [ - "file://.kiro/agents/aidlc-operations-agent.md", - "file://.kiro/knowledge/aidlc-operations-agent/*.md", - "file://.kiro/knowledge/aidlc-shared/*.md", - "file://aidlc/spaces/default/memory/**/*.md" - ], - "hooks": {} -} diff --git a/dist/kiro-ide/.kiro/agents/aidlc-operations-agent.md b/dist/kiro-ide/.kiro/agents/aidlc-operations-agent.md index fa3e09492..bb60a5898 100644 --- a/dist/kiro-ide/.kiro/agents/aidlc-operations-agent.md +++ b/dist/kiro-ide/.kiro/agents/aidlc-operations-agent.md @@ -8,8 +8,18 @@ description: > SRE and reliability engineer responsible for observability, incident response, and operational optimization. Leads Observability Setup, Incident Response, and Feedback & Optimization stages. Supports Performance Validation. -disallowedTools: Task tools: ["read", "write", "shell"] +permissions: + rules: + - capability: shell + effect: allow + match: + - "bun .kiro/tools/aidlc-*" + - "date -u *" + - capability: filesystem + effect: allow + match: + - "aidlc/spaces/**" --- **IMPORTANT: Do NOT use the Task tool. You operate as a delegated agent and must not spawn sub-agents.** diff --git a/dist/kiro-ide/.kiro/agents/aidlc-pipeline-deploy-agent.json b/dist/kiro-ide/.kiro/agents/aidlc-pipeline-deploy-agent.json deleted file mode 100644 index cd0f81b63..000000000 --- a/dist/kiro-ide/.kiro/agents/aidlc-pipeline-deploy-agent.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/aws/amazon-q-developer-cli/refs/heads/main/schemas/agent-v1.json", - "name": "aidlc-pipeline-deploy-agent", - "description": "AI-DLC Pipeline & Deploy Agent - delegation target for ensemble stages (CI/CD, deployment pipeline perspective).", - "prompt": "file://aidlc-pipeline-deploy-agent.md", - "tools": [ - "fs_read", - "fs_write", - "execute_bash", - "thinking" - ], - "allowedTools": [ - "fs_read", - "thinking" - ], - "toolsSettings": { - "execute_bash": { - "allowedCommands": [ - "bun \\.kiro/tools/.*", - "date -u .*" - ] - }, - "fs_write": { - "allowedPaths": [ - "aidlc/spaces/**" - ] - } - }, - "resources": [ - "file://.kiro/agents/aidlc-pipeline-deploy-agent.md", - "file://.kiro/knowledge/aidlc-pipeline-deploy-agent/*.md", - "file://.kiro/knowledge/aidlc-shared/*.md", - "file://aidlc/spaces/default/memory/**/*.md" - ], - "hooks": {} -} diff --git a/dist/kiro-ide/.kiro/agents/aidlc-pipeline-deploy-agent.md b/dist/kiro-ide/.kiro/agents/aidlc-pipeline-deploy-agent.md index 0c702432c..1aa2e2868 100644 --- a/dist/kiro-ide/.kiro/agents/aidlc-pipeline-deploy-agent.md +++ b/dist/kiro-ide/.kiro/agents/aidlc-pipeline-deploy-agent.md @@ -7,8 +7,18 @@ examples: description: > CI/CD engineer and release manager responsible for pipeline configuration, deployment strategy, and release execution. Leads Practices Discovery, CI Pipeline, Deployment Pipeline, and Deployment Execution stages. -disallowedTools: Task tools: ["read", "write", "shell"] +permissions: + rules: + - capability: shell + effect: allow + match: + - "bun .kiro/tools/aidlc-*" + - "date -u *" + - capability: filesystem + effect: allow + match: + - "aidlc/spaces/**" --- **IMPORTANT: Do NOT use the Task tool. You operate as a delegated agent and must not spawn sub-agents.** diff --git a/dist/kiro-ide/.kiro/agents/aidlc-product-agent.json b/dist/kiro-ide/.kiro/agents/aidlc-product-agent.json deleted file mode 100644 index c8c57fc60..000000000 --- a/dist/kiro-ide/.kiro/agents/aidlc-product-agent.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/aws/amazon-q-developer-cli/refs/heads/main/schemas/agent-v1.json", - "name": "aidlc-product-agent", - "description": "AI-DLC Product Agent - delegation target for ensemble stages (owner of intent capture, requirements, user stories; collaborator elsewhere).", - "prompt": "file://aidlc-product-agent.md", - "tools": [ - "fs_read", - "fs_write", - "execute_bash", - "thinking" - ], - "allowedTools": [ - "fs_read", - "thinking" - ], - "toolsSettings": { - "execute_bash": { - "allowedCommands": [ - "bun \\.kiro/tools/.*", - "date -u .*" - ] - }, - "fs_write": { - "allowedPaths": [ - "aidlc/spaces/**" - ] - } - }, - "resources": [ - "file://.kiro/agents/aidlc-product-agent.md", - "file://.kiro/knowledge/aidlc-product-agent/*.md", - "file://.kiro/knowledge/aidlc-shared/*.md", - "file://aidlc/spaces/default/memory/**/*.md" - ], - "hooks": {} -} diff --git a/dist/kiro-ide/.kiro/agents/aidlc-product-agent.md b/dist/kiro-ide/.kiro/agents/aidlc-product-agent.md index 9b84eed1f..29d271f90 100644 --- a/dist/kiro-ide/.kiro/agents/aidlc-product-agent.md +++ b/dist/kiro-ide/.kiro/agents/aidlc-product-agent.md @@ -7,8 +7,18 @@ examples: description: > Product manager and business analyst responsible for requirements, user stories, market research, and scope. Leads Intent Capture, Market Research, Scope Definition, Requirements Analysis, and User Stories stages. -disallowedTools: Task tools: ["read", "write", "shell"] +permissions: + rules: + - capability: shell + effect: allow + match: + - "bun .kiro/tools/aidlc-*" + - "date -u *" + - capability: filesystem + effect: allow + match: + - "aidlc/spaces/**" --- **IMPORTANT: Do NOT use the Task tool. You operate as a delegated agent and must not spawn sub-agents.** diff --git a/dist/kiro-ide/.kiro/agents/aidlc-product-lead-agent.json b/dist/kiro-ide/.kiro/agents/aidlc-product-lead-agent.json deleted file mode 100644 index 0f8a88092..000000000 --- a/dist/kiro-ide/.kiro/agents/aidlc-product-lead-agent.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/aws/amazon-q-developer-cli/refs/heads/main/schemas/agent-v1.json", - "name": "aidlc-product-lead-agent", - "description": "AI-DLC Product Lead Reviewer — delegation target for reviewing requirements, user stories, and mockups.", - "prompt": "file://aidlc-product-lead-agent.md", - "tools": [ - "fs_read", - "fs_write", - "execute_bash", - "thinking" - ], - "allowedTools": [ - "fs_read", - "fs_write", - "thinking" - ], - "toolsSettings": { - "execute_bash": { - "allowedCommands": [ - "bun \\.kiro/tools/.*", - "date -u .*" - ] - }, - "fs_write": { - "allowedPaths": [ - "aidlc/spaces/**" - ] - } - }, - "resources": [ - "file://.kiro/agents/aidlc-product-lead-agent.md", - "file://.kiro/knowledge/aidlc-product-lead-agent/*.md", - "file://.kiro/knowledge/aidlc-shared/*.md", - "file://aidlc/spaces/default/memory/**/*.md" - ], - "hooks": {} -} diff --git a/dist/kiro-ide/.kiro/agents/aidlc-product-lead-agent.md b/dist/kiro-ide/.kiro/agents/aidlc-product-lead-agent.md index 616348a96..94fac1fb0 100644 --- a/dist/kiro-ide/.kiro/agents/aidlc-product-lead-agent.md +++ b/dist/kiro-ide/.kiro/agents/aidlc-product-lead-agent.md @@ -3,8 +3,18 @@ name: aidlc-product-lead-agent display_name: Product Lead description: > Senior product leader who reviews requirements, user stories, and UX artifacts for completeness, business alignment, and testability. Does not produce — only reviews and challenges. Represents the customer's voice at the quality gate. -disallowedTools: Task tools: ["read", "write", "shell"] +permissions: + rules: + - capability: shell + effect: allow + match: + - "bun .kiro/tools/aidlc-*" + - "date -u *" + - capability: filesystem + effect: allow + match: + - "aidlc/spaces/**" --- **IMPORTANT: Do NOT use the Task tool. You operate as a delegated reviewer and must not spawn sub-agents.** diff --git a/dist/kiro-ide/.kiro/agents/aidlc-quality-agent.json b/dist/kiro-ide/.kiro/agents/aidlc-quality-agent.json deleted file mode 100644 index c61de8179..000000000 --- a/dist/kiro-ide/.kiro/agents/aidlc-quality-agent.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/aws/amazon-q-developer-cli/refs/heads/main/schemas/agent-v1.json", - "name": "aidlc-quality-agent", - "description": "AI-DLC Quality Agent - delegation target for ensemble stages (test strategy, testability, quality-gate perspective).", - "prompt": "file://aidlc-quality-agent.md", - "tools": [ - "fs_read", - "fs_write", - "execute_bash", - "thinking" - ], - "allowedTools": [ - "fs_read", - "thinking" - ], - "toolsSettings": { - "execute_bash": { - "allowedCommands": [ - "bun \\.kiro/tools/.*", - "date -u .*" - ] - }, - "fs_write": { - "allowedPaths": [ - "aidlc/spaces/**" - ] - } - }, - "resources": [ - "file://.kiro/agents/aidlc-quality-agent.md", - "file://.kiro/knowledge/aidlc-quality-agent/*.md", - "file://.kiro/knowledge/aidlc-shared/*.md", - "file://aidlc/spaces/default/memory/**/*.md" - ], - "hooks": {} -} diff --git a/dist/kiro-ide/.kiro/agents/aidlc-quality-agent.md b/dist/kiro-ide/.kiro/agents/aidlc-quality-agent.md index 70de7ee74..399e6484b 100644 --- a/dist/kiro-ide/.kiro/agents/aidlc-quality-agent.md +++ b/dist/kiro-ide/.kiro/agents/aidlc-quality-agent.md @@ -8,8 +8,18 @@ description: > QA lead responsible for test strategy, test case design, quality gates, and performance validation. Leads Build and Test and Performance Validation stages. Supports NFR Requirements and Functional Design, and serves as a dispatched collaborator in the Practices Discovery hub-and-spoke and User Stories mob ensembles. -disallowedTools: Task tools: ["read", "write", "shell"] +permissions: + rules: + - capability: shell + effect: allow + match: + - "bun .kiro/tools/aidlc-*" + - "date -u *" + - capability: filesystem + effect: allow + match: + - "aidlc/spaces/**" --- **IMPORTANT: Do NOT use the Task tool. You operate as a delegated agent and must not spawn sub-agents.** diff --git a/dist/kiro-ide/.kiro/agents/aidlc.json b/dist/kiro-ide/.kiro/agents/aidlc.json deleted file mode 100644 index 2061c3fe2..000000000 --- a/dist/kiro-ide/.kiro/agents/aidlc.json +++ /dev/null @@ -1,61 +0,0 @@ -{ - "name": "aidlc", - "description": "AI-DLC conductor agent \u2014 run /aidlc to start or resume a workflow", - "prompt": "You are a software development assistant in a project that uses AI-DLC (AI-Driven Development Life Cycle). When the user invokes /aidlc (or asks to start, resume, or manage an AI-DLC workflow), follow the aidlc skill exactly \u2014 it defines the forwarding loop and the engine that owns all routing. CRITICAL forwarding rules, which override any instinct to make progress yourself: (1) The engine binary aidlc-orchestrate.ts is the ONLY authority on the next move \u2014 run it, do EXACTLY what its single directive says, then report; never re-derive routing. (2) Your VERY FIRST action: append everything the user typed after /aidlc to the first `next` call unchanged \u2014 `/aidlc --phase ideation` MUST become `next --phase ideation`, never a bare `next`; dropping --phase/--stage sends the workflow to the wrong stage and is a bug. (3) When a directive is a print whose message names a command to run (e.g. aidlc-jump.ts execute ...), run THAT EXACT command as your immediate next tool call \u2014 do NOT run `next` again or read more files until it has run. Skipping the named command silently breaks the workflow. Outside of AI-DLC workflows, assist normally.", - "tools": [ - "fs_read", - "fs_write", - "execute_bash", - "todo_list", - "thinking", - "subagent" - ], - "allowedTools": [ - "fs_read", - "thinking", - "todo_list" - ], - "toolsSettings": { - "execute_bash": { - "allowedCommands": [ - "bun \\.kiro/tools/.*", - "bun \\${?KIRO_PROJECT_DIR}?/\\.kiro/tools/.*", - "date -u .*" - ], - "deniedCommands": [ - "rm -rf /.*", - "git push .*" - ] - }, - "fs_write": { - "allowedPaths": [ - "aidlc/spaces/**", - ".kiro/sensors/**", - "aidlc/.aidlc-compose-pending" - ] - }, - "subagent": { - "trustedAgents": [ - "aidlc-developer-agent", - "aidlc-architect-agent", - "aidlc-architecture-reviewer-agent", - "aidlc-product-lead-agent", - "aidlc-composer-agent", - "aidlc-product-agent", - "aidlc-design-agent", - "aidlc-delivery-agent", - "aidlc-aws-platform-agent", - "aidlc-compliance-agent", - "aidlc-devsecops-agent", - "aidlc-quality-agent", - "aidlc-pipeline-deploy-agent", - "aidlc-operations-agent" - ] - } - }, - "resources": [ - "skill://.kiro/skills/*/SKILL.md", - "file://aidlc/spaces/default/memory/**/*.md", - "file://AGENTS.md" - ] -} diff --git a/dist/kiro-ide/.kiro/agents/aidlc.md b/dist/kiro-ide/.kiro/agents/aidlc.md new file mode 100644 index 000000000..297797e27 --- /dev/null +++ b/dist/kiro-ide/.kiro/agents/aidlc.md @@ -0,0 +1,25 @@ +--- +name: aidlc +description: AI-DLC conductor agent — run /aidlc to start or resume a workflow +tools: ["read", "write", "shell", "subagent"] +permissions: + rules: + - capability: shell + effect: allow + match: + - "bun .kiro/tools/aidlc-*" + - "date -u *" + - capability: shell + effect: deny + match: + - "rm -rf *" + - "git push *" + - capability: filesystem + effect: allow + match: + - "aidlc/spaces/**" + - ".kiro/sensors/**" + - "aidlc/.aidlc-compose-pending" +--- + +You are a software development assistant in a project that uses AI-DLC (AI-Driven Development Life Cycle). When the user invokes /aidlc (or asks to start, resume, or manage an AI-DLC workflow), follow the aidlc skill exactly — it defines the forwarding loop and the engine that owns all routing. CRITICAL forwarding rules, which override any instinct to make progress yourself: (1) The engine binary aidlc-orchestrate.ts is the ONLY authority on the next move — run it, do EXACTLY what its single directive says, then report; never re-derive routing. (2) Your VERY FIRST action: append everything the user typed after /aidlc to the first `next` call unchanged — `/aidlc --phase ideation` MUST become `next --phase ideation`, never a bare `next`; dropping --phase/--stage sends the workflow to the wrong stage and is a bug. (3) When a directive is a print whose message names a command to run (e.g. aidlc-jump.ts execute ...), run THAT EXACT command as your immediate next tool call — do NOT run `next` again or read more files until it has run. Skipping the named command silently breaks the workflow. Outside of AI-DLC workflows, assist normally. diff --git a/dist/kiro-ide/.kiro/settings/cli.json b/dist/kiro-ide/.kiro/settings/cli.json deleted file mode 100644 index c61e0e825..000000000 --- a/dist/kiro-ide/.kiro/settings/cli.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "chat.defaultAgent": "aidlc", - "chat.modelDefaults": { - "claude-opus-4.8": { - "output_config": { - "effort": "xhigh" - } - } - } -} diff --git a/dist/kiro-ide/.kiro/tools/aidlc-lib.ts b/dist/kiro-ide/.kiro/tools/aidlc-lib.ts index 3906d2cec..0a81d8549 100644 --- a/dist/kiro-ide/.kiro/tools/aidlc-lib.ts +++ b/dist/kiro-ide/.kiro/tools/aidlc-lib.ts @@ -3926,7 +3926,14 @@ export function loadAgents(): AgentMetadata[] { const dir = agentsDir(); const slugToFile = new Map(); const agents: AgentMetadata[] = []; - const files = readdirSync(dir).filter((f) => f.endsWith(".md")).sort(); + // aidlc.md is the conductor MAIN (IDE custom-agent selector entry), not a + // stage lead/support agent — it carries no name/display_name/examples and + // must not enter the domain-agent roster (it would fail schema validation + // and pollute knownAgents used for stage lead_agent checks). Exclude it. + // No-op for harnesses that ship no aidlc.md (every tree but the Kiro IDE). + const files = readdirSync(dir) + .filter((f) => f.endsWith(".md") && f !== "aidlc.md") + .sort(); for (const f of files) { const filePath = join(dir, f); const agent = parseAgentFrontmatter(filePath); diff --git a/dist/kiro-ide/.kiro/tools/aidlc-utility.ts b/dist/kiro-ide/.kiro/tools/aidlc-utility.ts index 9b257f5ab..79cf8358f 100644 --- a/dist/kiro-ide/.kiro/tools/aidlc-utility.ts +++ b/dist/kiro-ide/.kiro/tools/aidlc-utility.ts @@ -1239,18 +1239,29 @@ function handleDoctor(projectDir: string, flags: Record = {}): v // permissions live there) plus settings/cli.json (activation). Codex CLI: // config.toml + hooks.json (the hook wiring) + rules/default.rules (permissions). if (harness === ".kiro") { - const agentPath = join(projectDir, harness, "agents", "aidlc.json"); + // The conductor agent config carries the hook + permission wiring. Kiro CLI + // ships it as agents/aidlc.json; Kiro IDE reads the Markdown agent format + // (agents/aidlc.md) instead — either satisfies the wiring requirement, so + // accept whichever is present. + const jsonAgentPath = join(projectDir, harness, "agents", "aidlc.json"); + const mdAgentPath = join(projectDir, harness, "agents", "aidlc.md"); results.push({ - pass: existsSync(agentPath), - label: "agents/aidlc.json present (hook + permission wiring)", - fix: "copy from `dist/kiro/.kiro/agents/aidlc.json`", - }); - const cliSettingsPath = join(projectDir, harness, "settings", "cli.json"); - results.push({ - pass: existsSync(cliSettingsPath), - label: "settings/cli.json present (workspace default-agent activation)", - fix: "copy from `dist/kiro/.kiro/settings/cli.json` (or use `kiro-cli chat --agent aidlc`)", + pass: existsSync(jsonAgentPath) || existsSync(mdAgentPath), + label: "agents/aidlc.{json,md} present (hook + permission wiring)", + fix: "copy from `dist/kiro/.kiro/agents/aidlc.json` (Kiro CLI) or `dist/kiro-ide/.kiro/agents/aidlc.md` (Kiro IDE)", }); + // settings/cli.json activates the default agent for Kiro CLI only. Kiro IDE + // activates via the agent selector and ships no settings file, so this check + // applies solely to a CLI install (aidlc.json present). Skip it for an IDE + // install (aidlc.md present, no aidlc.json). + if (existsSync(jsonAgentPath)) { + const cliSettingsPath = join(projectDir, harness, "settings", "cli.json"); + results.push({ + pass: existsSync(cliSettingsPath), + label: "settings/cli.json present (workspace default-agent activation)", + fix: "copy from `dist/kiro/.kiro/settings/cli.json` (or use `kiro-cli chat --agent aidlc`)", + }); + } } else if (harness === ".codex") { for (const [file, what, from] of [ ["config.toml", "model/provider/sandbox config", "dist/codex/.codex/config.toml"], diff --git a/dist/kiro-ide/.kiro/tools/aidlc-version.ts b/dist/kiro-ide/.kiro/tools/aidlc-version.ts index 0695010b6..49f646dce 100644 --- a/dist/kiro-ide/.kiro/tools/aidlc-version.ts +++ b/dist/kiro-ide/.kiro/tools/aidlc-version.ts @@ -1,4 +1,4 @@ // Hand-edited single source of truth for the AIDLC framework version. // Bumped in the same commit that adds the matching ## [N.N.N] heading // to CHANGELOG.md. Pinned by tests/unit/t68-version-changelog-sync.test.ts. -export const AIDLC_VERSION = "2.5.11"; +export const AIDLC_VERSION = "2.5.13"; diff --git a/dist/kiro-ide/AGENTS.md b/dist/kiro-ide/AGENTS.md index a9c912bc3..13090cbb0 100644 --- a/dist/kiro-ide/AGENTS.md +++ b/dist/kiro-ide/AGENTS.md @@ -16,7 +16,7 @@ This project uses AI-DLC (AI-Driven Development Life Cycle) for structured devel - **Skill**: `.kiro/skills/aidlc/` — Orchestrator (`SKILL.md`), stage protocol, and 32 stage files across 5 phase directories - **Session skills** (read-only, user-invocable): `.kiro/skills/aidlc-session-cost/`, `.kiro/skills/aidlc-replay/`, `.kiro/skills/aidlc-outcomes-pack/` — typed as `/aidlc-session-cost`, `/aidlc-replay`, `/aidlc-outcomes-pack`. Each pulls every count from `bun .kiro/tools/aidlc-runtime.ts summary --json` (no LLM-side counting). Classified `read-only`: they never advance the workflow stage pointer and never emit audit events. `aidlc-session-cost` and `aidlc-replay` print to the terminal only; `aidlc-outcomes-pack` is the only one that writes a file (`OUTCOMES.md`). - **Stage-runner skills** (user-invocable): `.kiro/skills/aidlc-/` — one per runnable core stage, typed as `/aidlc-` (e.g. `/aidlc-application-design`, `/aidlc-code-generation`); plugin-owned stages use their bare plugin-prefixed command name. Each runs that single stage in isolation via the engine's `--single` mode (`aidlc-orchestrate next --stage --single`) and **never advances your main workflow's `Current Stage`** — a single-stage run is isolated by design (the tool refuses to advance the main workflow). They are opt-in packaging: the same stage is reachable via `/aidlc --stage --single` without a runner. The runner set is generated from the compiled stage graph by `bun .kiro/tools/aidlc-runner-gen.ts write` and kept in sync by its `check` drift guard, so adding a stage file and regenerating adds its runner. The three bootstrap **initialization** stages ship no per-stage runner (they have no standalone meaning); the whole initialization phase is packaged as `/aidlc-init`, which mints the first intent and builds its state in one step. (This is opt-in packaging: the engine normally auto-births the first intent the moment you describe what to build — no separate initialization command is needed.) -- **Agents**: `.kiro/agents/` — 14 agents: 11 domain-expert personas (product, design, delivery, architect, aws-platform, compliance, devsecops, developer, quality, pipeline-deploy, operations), 2 review-only agents (product-lead, architecture-reviewer), and the adaptive-workflows composer. On Kiro IDE the `/aidlc` command loads `skills/aidlc/SKILL.md` as the conductor. The full 14-persona roster supplies workers for the four dispatched stages (2.1 pipeline, 2.2 subagent, 2.4 mob, 3.5 subagent), reviewer passes, and composer requests through Markdown personas with IDE-native tool grants; the shipped agent-v1 JSON files and `settings/cli.json` are CLI-only compatibility surfaces and do not select an IDE default agent. +- **Agents**: `.kiro/agents/` — 14 agents: 11 domain-expert personas (product, design, delivery, architect, aws-platform, compliance, devsecops, developer, quality, pipeline-deploy, operations), 2 review-only agents (product-lead, architecture-reviewer), and the adaptive-workflows composer. On Kiro IDE the `/aidlc` command loads `skills/aidlc/SKILL.md` as the conductor, and the conductor itself ships as `agents/aidlc.md` so it appears in the IDE agent selector. The full 14-persona roster supplies workers for the four dispatched stages (2.1 pipeline, 2.2 subagent, 2.4 mob, 3.5 subagent), reviewer passes, and composer requests through Markdown personas (`agents/*.md`) with IDE-native `tools:` grants and `permissions.rules`. The IDE resolves every agent from this Markdown frontmatter; no agent-v1 JSON or `settings/cli.json` ships here — those are Kiro CLI surfaces the IDE does not read. - **Method/rules**: `aidlc/spaces//memory/` — Layered files authored once at the workspace root, read by each harness via its native include (no copy into `.kiro/`): `org.md` (framework defaults + organisation-wide guardrails), `team.md` (this team's affirmed practices), `project.md` (project-specific specialisation), plus `phases/.md` for ideation, inception, construction, and operation (initialization is bootstrap-only and ships no rule file). Resolution is a strict-additive five-layer chain — `org → team → project → phase → stage` — where every applicable rule appears in `rules_in_context` at runtime. Conflicts (narrower contradicting broader policy) are rejected at the §13 learning admission check before the learning reaches disk. See `docs/reference/01-architecture.md` § "Configuration layers" and `docs/reference/08-rule-system.md` for the schema. - **Sensors**: `.kiro/sensors/` — Deterministic verification manifests (advisory). Ships with framework defaults (`aidlc-claim-sources.md`, `aidlc-required-sections.md`, `aidlc-upstream-coverage.md`, `aidlc-linter.md`, `aidlc-type-check.md`); forks may add custom `aidlc-.md` manifests. Stages declare which sensors fire via the frontmatter `sensors: []` list — a pull import resolved at compile time. The PostToolUse hook reads the compile-resolved `sensors_applicable` array off the stage graph node. - **Knowledge**: `.kiro/knowledge/` — Methodology reference. Per-agent under `aidlc--agent/` subfolders; `aidlc-shared/` holds cross-agent material. Ships with framework. diff --git a/dist/kiro/.kiro/tools/aidlc-lib.ts b/dist/kiro/.kiro/tools/aidlc-lib.ts index 3906d2cec..0a81d8549 100644 --- a/dist/kiro/.kiro/tools/aidlc-lib.ts +++ b/dist/kiro/.kiro/tools/aidlc-lib.ts @@ -3926,7 +3926,14 @@ export function loadAgents(): AgentMetadata[] { const dir = agentsDir(); const slugToFile = new Map(); const agents: AgentMetadata[] = []; - const files = readdirSync(dir).filter((f) => f.endsWith(".md")).sort(); + // aidlc.md is the conductor MAIN (IDE custom-agent selector entry), not a + // stage lead/support agent — it carries no name/display_name/examples and + // must not enter the domain-agent roster (it would fail schema validation + // and pollute knownAgents used for stage lead_agent checks). Exclude it. + // No-op for harnesses that ship no aidlc.md (every tree but the Kiro IDE). + const files = readdirSync(dir) + .filter((f) => f.endsWith(".md") && f !== "aidlc.md") + .sort(); for (const f of files) { const filePath = join(dir, f); const agent = parseAgentFrontmatter(filePath); diff --git a/dist/kiro/.kiro/tools/aidlc-utility.ts b/dist/kiro/.kiro/tools/aidlc-utility.ts index 9b257f5ab..79cf8358f 100644 --- a/dist/kiro/.kiro/tools/aidlc-utility.ts +++ b/dist/kiro/.kiro/tools/aidlc-utility.ts @@ -1239,18 +1239,29 @@ function handleDoctor(projectDir: string, flags: Record = {}): v // permissions live there) plus settings/cli.json (activation). Codex CLI: // config.toml + hooks.json (the hook wiring) + rules/default.rules (permissions). if (harness === ".kiro") { - const agentPath = join(projectDir, harness, "agents", "aidlc.json"); + // The conductor agent config carries the hook + permission wiring. Kiro CLI + // ships it as agents/aidlc.json; Kiro IDE reads the Markdown agent format + // (agents/aidlc.md) instead — either satisfies the wiring requirement, so + // accept whichever is present. + const jsonAgentPath = join(projectDir, harness, "agents", "aidlc.json"); + const mdAgentPath = join(projectDir, harness, "agents", "aidlc.md"); results.push({ - pass: existsSync(agentPath), - label: "agents/aidlc.json present (hook + permission wiring)", - fix: "copy from `dist/kiro/.kiro/agents/aidlc.json`", - }); - const cliSettingsPath = join(projectDir, harness, "settings", "cli.json"); - results.push({ - pass: existsSync(cliSettingsPath), - label: "settings/cli.json present (workspace default-agent activation)", - fix: "copy from `dist/kiro/.kiro/settings/cli.json` (or use `kiro-cli chat --agent aidlc`)", + pass: existsSync(jsonAgentPath) || existsSync(mdAgentPath), + label: "agents/aidlc.{json,md} present (hook + permission wiring)", + fix: "copy from `dist/kiro/.kiro/agents/aidlc.json` (Kiro CLI) or `dist/kiro-ide/.kiro/agents/aidlc.md` (Kiro IDE)", }); + // settings/cli.json activates the default agent for Kiro CLI only. Kiro IDE + // activates via the agent selector and ships no settings file, so this check + // applies solely to a CLI install (aidlc.json present). Skip it for an IDE + // install (aidlc.md present, no aidlc.json). + if (existsSync(jsonAgentPath)) { + const cliSettingsPath = join(projectDir, harness, "settings", "cli.json"); + results.push({ + pass: existsSync(cliSettingsPath), + label: "settings/cli.json present (workspace default-agent activation)", + fix: "copy from `dist/kiro/.kiro/settings/cli.json` (or use `kiro-cli chat --agent aidlc`)", + }); + } } else if (harness === ".codex") { for (const [file, what, from] of [ ["config.toml", "model/provider/sandbox config", "dist/codex/.codex/config.toml"], diff --git a/dist/kiro/.kiro/tools/aidlc-version.ts b/dist/kiro/.kiro/tools/aidlc-version.ts index 0695010b6..49f646dce 100644 --- a/dist/kiro/.kiro/tools/aidlc-version.ts +++ b/dist/kiro/.kiro/tools/aidlc-version.ts @@ -1,4 +1,4 @@ // Hand-edited single source of truth for the AIDLC framework version. // Bumped in the same commit that adds the matching ## [N.N.N] heading // to CHANGELOG.md. Pinned by tests/unit/t68-version-changelog-sync.test.ts. -export const AIDLC_VERSION = "2.5.11"; +export const AIDLC_VERSION = "2.5.13"; diff --git a/dist/opencode/.aidlc/tools/aidlc-lib.ts b/dist/opencode/.aidlc/tools/aidlc-lib.ts index 3906d2cec..0a81d8549 100644 --- a/dist/opencode/.aidlc/tools/aidlc-lib.ts +++ b/dist/opencode/.aidlc/tools/aidlc-lib.ts @@ -3926,7 +3926,14 @@ export function loadAgents(): AgentMetadata[] { const dir = agentsDir(); const slugToFile = new Map(); const agents: AgentMetadata[] = []; - const files = readdirSync(dir).filter((f) => f.endsWith(".md")).sort(); + // aidlc.md is the conductor MAIN (IDE custom-agent selector entry), not a + // stage lead/support agent — it carries no name/display_name/examples and + // must not enter the domain-agent roster (it would fail schema validation + // and pollute knownAgents used for stage lead_agent checks). Exclude it. + // No-op for harnesses that ship no aidlc.md (every tree but the Kiro IDE). + const files = readdirSync(dir) + .filter((f) => f.endsWith(".md") && f !== "aidlc.md") + .sort(); for (const f of files) { const filePath = join(dir, f); const agent = parseAgentFrontmatter(filePath); diff --git a/dist/opencode/.aidlc/tools/aidlc-utility.ts b/dist/opencode/.aidlc/tools/aidlc-utility.ts index 9b257f5ab..79cf8358f 100644 --- a/dist/opencode/.aidlc/tools/aidlc-utility.ts +++ b/dist/opencode/.aidlc/tools/aidlc-utility.ts @@ -1239,18 +1239,29 @@ function handleDoctor(projectDir: string, flags: Record = {}): v // permissions live there) plus settings/cli.json (activation). Codex CLI: // config.toml + hooks.json (the hook wiring) + rules/default.rules (permissions). if (harness === ".kiro") { - const agentPath = join(projectDir, harness, "agents", "aidlc.json"); + // The conductor agent config carries the hook + permission wiring. Kiro CLI + // ships it as agents/aidlc.json; Kiro IDE reads the Markdown agent format + // (agents/aidlc.md) instead — either satisfies the wiring requirement, so + // accept whichever is present. + const jsonAgentPath = join(projectDir, harness, "agents", "aidlc.json"); + const mdAgentPath = join(projectDir, harness, "agents", "aidlc.md"); results.push({ - pass: existsSync(agentPath), - label: "agents/aidlc.json present (hook + permission wiring)", - fix: "copy from `dist/kiro/.kiro/agents/aidlc.json`", - }); - const cliSettingsPath = join(projectDir, harness, "settings", "cli.json"); - results.push({ - pass: existsSync(cliSettingsPath), - label: "settings/cli.json present (workspace default-agent activation)", - fix: "copy from `dist/kiro/.kiro/settings/cli.json` (or use `kiro-cli chat --agent aidlc`)", + pass: existsSync(jsonAgentPath) || existsSync(mdAgentPath), + label: "agents/aidlc.{json,md} present (hook + permission wiring)", + fix: "copy from `dist/kiro/.kiro/agents/aidlc.json` (Kiro CLI) or `dist/kiro-ide/.kiro/agents/aidlc.md` (Kiro IDE)", }); + // settings/cli.json activates the default agent for Kiro CLI only. Kiro IDE + // activates via the agent selector and ships no settings file, so this check + // applies solely to a CLI install (aidlc.json present). Skip it for an IDE + // install (aidlc.md present, no aidlc.json). + if (existsSync(jsonAgentPath)) { + const cliSettingsPath = join(projectDir, harness, "settings", "cli.json"); + results.push({ + pass: existsSync(cliSettingsPath), + label: "settings/cli.json present (workspace default-agent activation)", + fix: "copy from `dist/kiro/.kiro/settings/cli.json` (or use `kiro-cli chat --agent aidlc`)", + }); + } } else if (harness === ".codex") { for (const [file, what, from] of [ ["config.toml", "model/provider/sandbox config", "dist/codex/.codex/config.toml"], diff --git a/dist/opencode/.aidlc/tools/aidlc-version.ts b/dist/opencode/.aidlc/tools/aidlc-version.ts index 0695010b6..49f646dce 100644 --- a/dist/opencode/.aidlc/tools/aidlc-version.ts +++ b/dist/opencode/.aidlc/tools/aidlc-version.ts @@ -1,4 +1,4 @@ // Hand-edited single source of truth for the AIDLC framework version. // Bumped in the same commit that adds the matching ## [N.N.N] heading // to CHANGELOG.md. Pinned by tests/unit/t68-version-changelog-sync.test.ts. -export const AIDLC_VERSION = "2.5.11"; +export const AIDLC_VERSION = "2.5.13"; diff --git a/dist/plugins/test-pro/claude/hooks/compose.ts b/dist/plugins/test-pro/claude/hooks/compose.ts index 9bfdfe4aa..1582acdb8 100644 --- a/dist/plugins/test-pro/claude/hooks/compose.ts +++ b/dist/plugins/test-pro/claude/hooks/compose.ts @@ -607,13 +607,51 @@ function pluginShipsViableOpencodeAgent(agent: string): boolean { return !collidingFile || collidingFile === join(nativeAgentsDir, `${agent}.md`); } -// Kiro, Codex, and OpenCode cannot dispatch a Markdown-only persona from the -// engine roster. Kiro requires BOTH a hand-authored agent-v1 JSON and conductor -// trustedAgents registration; Codex requires an agent config TOML; OpenCode -// requires a native `.opencode/agents/.md` subagent (installed, or viably -// shipped by this plugin — see pluginShipsViableOpencodeAgent). Reject any +// Kiro CLI, Codex, and OpenCode cannot dispatch a Markdown-only persona from the +// engine roster. Kiro CLI requires BOTH a hand-authored agent-v1 JSON and +// conductor trustedAgents registration; Codex requires an agent config TOML; +// OpenCode requires a native `.opencode/agents/.md` subagent (installed, or +// viably shipped by this plugin — see pluginShipsViableOpencodeAgent). Reject any // dispatched stage whose lead, support, or reviewer lacks that complete // surface. Markdown personas remain composable for accepted inline stages. +// +// KIRO CLI vs KIRO IDE. Both install under `.kiro`, so HARNESS_LEAF alone cannot +// tell them apart — the discriminator is the conductor's own shape: the CLI ships +// `agents/aidlc.json` (agent-v1, carrying the trustedAgents roster), while the IDE +// reads Markdown agents and ships `agents/aidlc.md` with no JSON at all. +// +// The IDE's dispatch surface is NOT "a Markdown persona exists". IDE 1.0 delegation +// needs a `tools:` grant AND a `permissions.rules` block on the target agent +// (harness/kiro-ide/manifest.ts:71-72 appends both to every core persona). A plugin +// agent ships neither, and compose applies no IDE projection when it copies one +// (unlike `.aidlc`, where projectOpencodeAgentMemory rewrites the twin). Copying it +// verbatim yields an agent that is dispatched but cannot read, write, or run +// anything — a silent capability hole, not support. +// +// So the IDE requirement is real, just different from the CLI's, and compose cannot +// satisfy it today: deciding which grants to inject is the packager's job +// (frontmatterAdditions), not the composer's. Until an IDE projection exists, the +// IDE follows the documented contract for every other harness whose surface a +// plugin cannot ship — REJECT the dispatched stage and drop-log it +// (docs/reference/18-plugin-mechanism.md). Rejecting is the honest state: it tells +// the plugin author the stage will not dispatch, instead of composing a stage that +// fails at runtime. +// Is an INSTALLED Kiro IDE agent `.md` actually dispatchable? IDE 1.0 delegation +// needs a `tools:` grant and a `permissions.rules` block; the packager appends both +// to every core persona (harness/kiro-ide/manifest.ts:71-72). A file that lacks +// them is dispatched with no capabilities, which is why existence alone is not the +// surface on this harness. Missing file → not dispatchable (same verdict). +function installedIdeAgentIsDispatchable(agentsDir: string, agent: string): boolean { + let content: string; + try { + content = readFileSync(join(agentsDir, `${agent}.md`), "utf-8"); + } catch { + return false; + } + const fm = frontmatter(content); + return /^tools:/m.test(fm) && /^permissions:/m.test(fm); +} + async function kiroPluginAgentPrechecks(): Promise { if ( HARNESS_LEAF !== ".kiro" && @@ -622,16 +660,26 @@ async function kiroPluginAgentPrechecks(): Promise(); - if (HARNESS_LEAF === ".kiro") { + if (isKiroCli) { try { const conductor = JSON.parse( readFileSync(join(HARNESS_DIR, "agents", "aidlc.json"), "utf-8"), @@ -657,11 +705,13 @@ async function kiroPluginAgentPrechecks(): Promise.md` subagent (installed, or viably -// shipped by this plugin — see pluginShipsViableOpencodeAgent). Reject any +// Kiro CLI, Codex, and OpenCode cannot dispatch a Markdown-only persona from the +// engine roster. Kiro CLI requires BOTH a hand-authored agent-v1 JSON and +// conductor trustedAgents registration; Codex requires an agent config TOML; +// OpenCode requires a native `.opencode/agents/.md` subagent (installed, or +// viably shipped by this plugin — see pluginShipsViableOpencodeAgent). Reject any // dispatched stage whose lead, support, or reviewer lacks that complete // surface. Markdown personas remain composable for accepted inline stages. +// +// KIRO CLI vs KIRO IDE. Both install under `.kiro`, so HARNESS_LEAF alone cannot +// tell them apart — the discriminator is the conductor's own shape: the CLI ships +// `agents/aidlc.json` (agent-v1, carrying the trustedAgents roster), while the IDE +// reads Markdown agents and ships `agents/aidlc.md` with no JSON at all. +// +// The IDE's dispatch surface is NOT "a Markdown persona exists". IDE 1.0 delegation +// needs a `tools:` grant AND a `permissions.rules` block on the target agent +// (harness/kiro-ide/manifest.ts:71-72 appends both to every core persona). A plugin +// agent ships neither, and compose applies no IDE projection when it copies one +// (unlike `.aidlc`, where projectOpencodeAgentMemory rewrites the twin). Copying it +// verbatim yields an agent that is dispatched but cannot read, write, or run +// anything — a silent capability hole, not support. +// +// So the IDE requirement is real, just different from the CLI's, and compose cannot +// satisfy it today: deciding which grants to inject is the packager's job +// (frontmatterAdditions), not the composer's. Until an IDE projection exists, the +// IDE follows the documented contract for every other harness whose surface a +// plugin cannot ship — REJECT the dispatched stage and drop-log it +// (docs/reference/18-plugin-mechanism.md). Rejecting is the honest state: it tells +// the plugin author the stage will not dispatch, instead of composing a stage that +// fails at runtime. +// Is an INSTALLED Kiro IDE agent `.md` actually dispatchable? IDE 1.0 delegation +// needs a `tools:` grant and a `permissions.rules` block; the packager appends both +// to every core persona (harness/kiro-ide/manifest.ts:71-72). A file that lacks +// them is dispatched with no capabilities, which is why existence alone is not the +// surface on this harness. Missing file → not dispatchable (same verdict). +function installedIdeAgentIsDispatchable(agentsDir: string, agent: string): boolean { + let content: string; + try { + content = readFileSync(join(agentsDir, `${agent}.md`), "utf-8"); + } catch { + return false; + } + const fm = frontmatter(content); + return /^tools:/m.test(fm) && /^permissions:/m.test(fm); +} + async function kiroPluginAgentPrechecks(): Promise { if ( HARNESS_LEAF !== ".kiro" && @@ -622,16 +660,26 @@ async function kiroPluginAgentPrechecks(): Promise(); - if (HARNESS_LEAF === ".kiro") { + if (isKiroCli) { try { const conductor = JSON.parse( readFileSync(join(HARNESS_DIR, "agents", "aidlc.json"), "utf-8"), @@ -657,11 +705,13 @@ async function kiroPluginAgentPrechecks(): Promise.md` subagent (installed, or viably -// shipped by this plugin — see pluginShipsViableOpencodeAgent). Reject any +// Kiro CLI, Codex, and OpenCode cannot dispatch a Markdown-only persona from the +// engine roster. Kiro CLI requires BOTH a hand-authored agent-v1 JSON and +// conductor trustedAgents registration; Codex requires an agent config TOML; +// OpenCode requires a native `.opencode/agents/.md` subagent (installed, or +// viably shipped by this plugin — see pluginShipsViableOpencodeAgent). Reject any // dispatched stage whose lead, support, or reviewer lacks that complete // surface. Markdown personas remain composable for accepted inline stages. +// +// KIRO CLI vs KIRO IDE. Both install under `.kiro`, so HARNESS_LEAF alone cannot +// tell them apart — the discriminator is the conductor's own shape: the CLI ships +// `agents/aidlc.json` (agent-v1, carrying the trustedAgents roster), while the IDE +// reads Markdown agents and ships `agents/aidlc.md` with no JSON at all. +// +// The IDE's dispatch surface is NOT "a Markdown persona exists". IDE 1.0 delegation +// needs a `tools:` grant AND a `permissions.rules` block on the target agent +// (harness/kiro-ide/manifest.ts:71-72 appends both to every core persona). A plugin +// agent ships neither, and compose applies no IDE projection when it copies one +// (unlike `.aidlc`, where projectOpencodeAgentMemory rewrites the twin). Copying it +// verbatim yields an agent that is dispatched but cannot read, write, or run +// anything — a silent capability hole, not support. +// +// So the IDE requirement is real, just different from the CLI's, and compose cannot +// satisfy it today: deciding which grants to inject is the packager's job +// (frontmatterAdditions), not the composer's. Until an IDE projection exists, the +// IDE follows the documented contract for every other harness whose surface a +// plugin cannot ship — REJECT the dispatched stage and drop-log it +// (docs/reference/18-plugin-mechanism.md). Rejecting is the honest state: it tells +// the plugin author the stage will not dispatch, instead of composing a stage that +// fails at runtime. +// Is an INSTALLED Kiro IDE agent `.md` actually dispatchable? IDE 1.0 delegation +// needs a `tools:` grant and a `permissions.rules` block; the packager appends both +// to every core persona (harness/kiro-ide/manifest.ts:71-72). A file that lacks +// them is dispatched with no capabilities, which is why existence alone is not the +// surface on this harness. Missing file → not dispatchable (same verdict). +function installedIdeAgentIsDispatchable(agentsDir: string, agent: string): boolean { + let content: string; + try { + content = readFileSync(join(agentsDir, `${agent}.md`), "utf-8"); + } catch { + return false; + } + const fm = frontmatter(content); + return /^tools:/m.test(fm) && /^permissions:/m.test(fm); +} + async function kiroPluginAgentPrechecks(): Promise { if ( HARNESS_LEAF !== ".kiro" && @@ -622,16 +660,26 @@ async function kiroPluginAgentPrechecks(): Promise(); - if (HARNESS_LEAF === ".kiro") { + if (isKiroCli) { try { const conductor = JSON.parse( readFileSync(join(HARNESS_DIR, "agents", "aidlc.json"), "utf-8"), @@ -657,11 +705,13 @@ async function kiroPluginAgentPrechecks(): Promise.md` subagent (installed, or viably -// shipped by this plugin — see pluginShipsViableOpencodeAgent). Reject any +// Kiro CLI, Codex, and OpenCode cannot dispatch a Markdown-only persona from the +// engine roster. Kiro CLI requires BOTH a hand-authored agent-v1 JSON and +// conductor trustedAgents registration; Codex requires an agent config TOML; +// OpenCode requires a native `.opencode/agents/.md` subagent (installed, or +// viably shipped by this plugin — see pluginShipsViableOpencodeAgent). Reject any // dispatched stage whose lead, support, or reviewer lacks that complete // surface. Markdown personas remain composable for accepted inline stages. +// +// KIRO CLI vs KIRO IDE. Both install under `.kiro`, so HARNESS_LEAF alone cannot +// tell them apart — the discriminator is the conductor's own shape: the CLI ships +// `agents/aidlc.json` (agent-v1, carrying the trustedAgents roster), while the IDE +// reads Markdown agents and ships `agents/aidlc.md` with no JSON at all. +// +// The IDE's dispatch surface is NOT "a Markdown persona exists". IDE 1.0 delegation +// needs a `tools:` grant AND a `permissions.rules` block on the target agent +// (harness/kiro-ide/manifest.ts:71-72 appends both to every core persona). A plugin +// agent ships neither, and compose applies no IDE projection when it copies one +// (unlike `.aidlc`, where projectOpencodeAgentMemory rewrites the twin). Copying it +// verbatim yields an agent that is dispatched but cannot read, write, or run +// anything — a silent capability hole, not support. +// +// So the IDE requirement is real, just different from the CLI's, and compose cannot +// satisfy it today: deciding which grants to inject is the packager's job +// (frontmatterAdditions), not the composer's. Until an IDE projection exists, the +// IDE follows the documented contract for every other harness whose surface a +// plugin cannot ship — REJECT the dispatched stage and drop-log it +// (docs/reference/18-plugin-mechanism.md). Rejecting is the honest state: it tells +// the plugin author the stage will not dispatch, instead of composing a stage that +// fails at runtime. +// Is an INSTALLED Kiro IDE agent `.md` actually dispatchable? IDE 1.0 delegation +// needs a `tools:` grant and a `permissions.rules` block; the packager appends both +// to every core persona (harness/kiro-ide/manifest.ts:71-72). A file that lacks +// them is dispatched with no capabilities, which is why existence alone is not the +// surface on this harness. Missing file → not dispatchable (same verdict). +function installedIdeAgentIsDispatchable(agentsDir: string, agent: string): boolean { + let content: string; + try { + content = readFileSync(join(agentsDir, `${agent}.md`), "utf-8"); + } catch { + return false; + } + const fm = frontmatter(content); + return /^tools:/m.test(fm) && /^permissions:/m.test(fm); +} + async function kiroPluginAgentPrechecks(): Promise { if ( HARNESS_LEAF !== ".kiro" && @@ -622,16 +660,26 @@ async function kiroPluginAgentPrechecks(): Promise(); - if (HARNESS_LEAF === ".kiro") { + if (isKiroCli) { try { const conductor = JSON.parse( readFileSync(join(HARNESS_DIR, "agents", "aidlc.json"), "utf-8"), @@ -657,11 +705,13 @@ async function kiroPluginAgentPrechecks(): Promise.md` subagent (installed, or viably -// shipped by this plugin — see pluginShipsViableOpencodeAgent). Reject any +// Kiro CLI, Codex, and OpenCode cannot dispatch a Markdown-only persona from the +// engine roster. Kiro CLI requires BOTH a hand-authored agent-v1 JSON and +// conductor trustedAgents registration; Codex requires an agent config TOML; +// OpenCode requires a native `.opencode/agents/.md` subagent (installed, or +// viably shipped by this plugin — see pluginShipsViableOpencodeAgent). Reject any // dispatched stage whose lead, support, or reviewer lacks that complete // surface. Markdown personas remain composable for accepted inline stages. +// +// KIRO CLI vs KIRO IDE. Both install under `.kiro`, so HARNESS_LEAF alone cannot +// tell them apart — the discriminator is the conductor's own shape: the CLI ships +// `agents/aidlc.json` (agent-v1, carrying the trustedAgents roster), while the IDE +// reads Markdown agents and ships `agents/aidlc.md` with no JSON at all. +// +// The IDE's dispatch surface is NOT "a Markdown persona exists". IDE 1.0 delegation +// needs a `tools:` grant AND a `permissions.rules` block on the target agent +// (harness/kiro-ide/manifest.ts:71-72 appends both to every core persona). A plugin +// agent ships neither, and compose applies no IDE projection when it copies one +// (unlike `.aidlc`, where projectOpencodeAgentMemory rewrites the twin). Copying it +// verbatim yields an agent that is dispatched but cannot read, write, or run +// anything — a silent capability hole, not support. +// +// So the IDE requirement is real, just different from the CLI's, and compose cannot +// satisfy it today: deciding which grants to inject is the packager's job +// (frontmatterAdditions), not the composer's. Until an IDE projection exists, the +// IDE follows the documented contract for every other harness whose surface a +// plugin cannot ship — REJECT the dispatched stage and drop-log it +// (docs/reference/18-plugin-mechanism.md). Rejecting is the honest state: it tells +// the plugin author the stage will not dispatch, instead of composing a stage that +// fails at runtime. +// Is an INSTALLED Kiro IDE agent `.md` actually dispatchable? IDE 1.0 delegation +// needs a `tools:` grant and a `permissions.rules` block; the packager appends both +// to every core persona (harness/kiro-ide/manifest.ts:71-72). A file that lacks +// them is dispatched with no capabilities, which is why existence alone is not the +// surface on this harness. Missing file → not dispatchable (same verdict). +function installedIdeAgentIsDispatchable(agentsDir: string, agent: string): boolean { + let content: string; + try { + content = readFileSync(join(agentsDir, `${agent}.md`), "utf-8"); + } catch { + return false; + } + const fm = frontmatter(content); + return /^tools:/m.test(fm) && /^permissions:/m.test(fm); +} + async function kiroPluginAgentPrechecks(): Promise { if ( HARNESS_LEAF !== ".kiro" && @@ -622,16 +660,26 @@ async function kiroPluginAgentPrechecks(): Promise(); - if (HARNESS_LEAF === ".kiro") { + if (isKiroCli) { try { const conductor = JSON.parse( readFileSync(join(HARNESS_DIR, "agents", "aidlc.json"), "utf-8"), @@ -657,11 +705,13 @@ async function kiroPluginAgentPrechecks(): Promise= 1.0) + `.kiro/hooks/aidlc-*.kiro.hook` legacy files (pre-1.0); both shipped, no double-firing | | Gates & questions | `AskUserQuestion` widget | Numbered prose options (reply with a number); the questions FILE with `[Answer]:` tags stays the source of truth | | Statusline | Current stage + model + context % | Not available — use `/aidlc --status` and the progress line at each gate | -| Dispatched stages (2.1 pipeline, 2.2 subagent, 2.4 mob, 3.5 subagent) | `Task` tool | Kiro `subagent` tool → the agent configs (all 14 personas); the IDE reads a delegate's tool grants from the agent `.md` frontmatter (`tools:`), injected at packaging - the agent-v1 JSONs are CLI-only | +| Dispatched stages (2.1 pipeline, 2.2 subagent, 2.4 mob, 3.5 subagent) | `Task` tool | Kiro `subagent` tool → the Markdown personas (all 14, `agents/*.md`); the IDE reads a delegate's tool grants from the agent `.md` frontmatter (`tools:`), injected at packaging | | Construction swarm | Parallel `Task` floor, optional ultracode Workflow | Subagent fan-out only; `AIDLC_USE_SWARM=1` is announced as a no-op | | Session audit events | `SESSION_STARTED/RESUMED/ENDED`, `SESSION_COMPACTED` | `SESSION_STARTED` only on IDE 1.x (no genuine session-end trigger — `SESSION_ENDED` is recorded only by the legacy hook on pre-1.0 builds; no pre-compaction event) | | MCP servers | Ships 5 (`.mcp.json`: `context7` + four AWS servers) | None shipped | @@ -165,20 +167,30 @@ workflow. substituted to `.kiro` and the `rules/` → `steering/` rename). `bun scripts/package.ts --check` is the drift guard and runs in CI. The authored Kiro IDE surfaces live in `harness/kiro-ide/`: the orchestrator skill -(`skills/aidlc/`), CLI-compatibility agent JSONs (`agents/`), the hook adapter -and v2 hook JSON files (`hooks/`), CLI-only `settings/cli.json`, and -`AGENTS.md` — edit those (or `core/`), never the generated `dist/kiro-ide`. - -The IDE harness differs from the CLI harness (`harness/kiro/`) in three ways: -the `/aidlc` skill is its conductor rather than an agent selected through -`settings/cli.json`; it ships v2 hook JSON files (the CLI relies on the -agent-JSON `hooks` block, which the IDE ignores); and its manifest injects a -`tools:` frontmatter grant into the delegation-target agent `.md` files -(`frontmatterAdditions`), because the IDE resolves a delegated subagent's tools -from the `.md` frontmatter rather than the agent-v1 JSON - without the grant an -IDE delegate runs toolless. Note the frontmatter grant is unscoped (the IDE has -no `allowedCommands`/`allowedPaths` equivalent there), wider than the CLI JSON -sandbox. +(`skills/aidlc/`), the conductor `agents/aidlc.md` (the IDE selector entry), the +hook adapter and hook manifests (`hooks/`), and `AGENTS.md` — edit those (or +`core/`), never the generated `dist/kiro-ide`. + +The IDE harness differs from the CLI harness (`harness/kiro/`) in three ways. +First, agents ship as Markdown only: the manifest omits the CLI's agent-v1 JSONs +and `settings/cli.json` (surfaces the IDE does not read), and the `/aidlc` skill +is the conductor rather than an agent selected through `settings/cli.json` — the +conductor still ships as `agents/aidlc.md` so it appears in the IDE selector. +Second, it ships v2 hook JSON manifests (the CLI relies on the agent-JSON +`hooks` block, which the IDE ignores). Third, its manifest injects a `tools:` +frontmatter grant and a `permissions.rules` block into the delegation-target +agent `.md` files (`frontmatterAdditions`) and drops the CLI-only +`disallowedTools` field (`frontmatterRemovals`), because the IDE resolves a +delegated subagent's tools from the `.md` frontmatter rather than the agent-v1 +JSON — without the grant an IDE delegate runs toolless. The IDE has no +`allowedCommands`/`allowedPaths` equivalent for a delegate; the 1.0 +`permissions.rules` capability/effect/match model is what the injected block +carries instead. Read those rules as **autoapprovals, not a sandbox**: Kiro +defaults an unmatched operation to `ask`, so the shell and filesystem lists +decide what a delegate may do without a consent prompt — they do not confine it. +The shell list is `bun .kiro/tools/aidlc-*` plus `date -u *`, the glob equivalent +of the CLI JSON's `bun \.kiro/tools/.*` regex, kept to the engine's real command +surface rather than a blanket `bun *`. See [Porting to a New Harness](../../harness-engineering/09-porting-to-a-new-harness.md). ## Next steps diff --git a/docs/reference/14-claude-features.md b/docs/reference/14-claude-features.md index 45ec0ffd3..6445a4d21 100644 --- a/docs/reference/14-claude-features.md +++ b/docs/reference/14-claude-features.md @@ -23,7 +23,7 @@ harness parameter. Add a column when you port to a new harness. | **Orchestrator entry** (`/aidlc` + runners) | Skills (`/aidlc`) | Skills (`/aidlc`) | Skills (`/aidlc`) | Skills (`$aidlc`) | Command → skill (`/aidlc`; skills from `.aidlc/skills` via `skills.paths`) | | **Agent personas** (14 total) | `.claude/agents/*.md` | `.kiro/agents/*.json` + persona `.md` | Persona `.md`; delegation targets add IDE `tools:` grants | `.codex/agents/` TOMLs | `.opencode/agents/*.md` (subagents) + persona `.md` | | **Automation** (audit, state, tracking) | Hooks via `settings.json` | Hooks via `agents/aidlc.json` | `.kiro/hooks/aidlc-*.json` (v2, IDE >= 1.0) + `.kiro/hooks/aidlc-*.kiro.hook` (legacy, pre-1.0) | Hooks via `.codex/hooks.json` (one adapter) | Adapter plugin (`.opencode/plugin/`) | -| **Standing rules** (the layer chain) | `aidlc/spaces//memory/` (via `.claude/rules/aidlc.md` @-import stub) | `aidlc/spaces//memory/` (via Kiro resources glob) | `aidlc/spaces//memory/` (via Kiro resources glob) | `aidlc/spaces//memory/` (via `AIDLC_RULES_DIR`) | `aidlc/spaces//memory/` (via `instructions` glob) | +| **Standing rules** (the layer chain) | `aidlc/spaces//memory/` (via `.claude/rules/aidlc.md` @-import stub) | `aidlc/spaces//memory/` (via Kiro resources glob) | `aidlc/spaces//memory/` (read directly from the seeded workspace shell) | `aidlc/spaces//memory/` (via `AIDLC_RULES_DIR`) | `aidlc/spaces//memory/` (via `instructions` glob) | | **Project onboarding doc** | `CLAUDE.md` | `AGENTS.md` | `AGENTS.md` | `AGENTS.md` | `AGENTS.md` | | **Permissions / config** | `.claude/settings.json` | `.kiro/settings/cli.json` + agent config | Agent `.md` `tools:` frontmatter for delegates | `.codex/config.toml` (+ Starlark `rules/`) | `opencode.json` (project root) | diff --git a/docs/reference/18-plugin-mechanism.md b/docs/reference/18-plugin-mechanism.md index ce88cf1e0..374d4d40f 100644 --- a/docs/reference/18-plugin-mechanism.md +++ b/docs/reference/18-plugin-mechanism.md @@ -307,6 +307,18 @@ plugin's own files never satisfy those checks. Hand-authoring the missing surface and re-running compose accepts the stage. The Markdown persona remains composed for any accepted inline stage that also uses it. +On **Kiro IDE** the surface is the agent's own Markdown, but existence is not +enough: IDE 1.0 delegation requires a `tools:` grant and a `permissions.rules` +block on the target agent, which the packager appends to every core persona. A +plugin agent ships neither, and compose applies no IDE projection when it copies +one (unlike OpenCode, whose native twin it rewrites) — copying it verbatim would +yield an agent that dispatches but can neither read, write, nor run anything. +Deciding which grants to inject belongs to the packager, not the composer, so +until an IDE projection exists compose **rejects** plugin-dispatched stages on +this harness and drop-logs the remediation (author the agent `.md` carrying both +blocks, or change the stage to `mode: inline`). Inline plugin stages are +unaffected on the IDE, as on every other harness. + `agent-team` is schema-reserved but has no runtime consumer, so compose rejects plugin stages that select it on every harness instead of silently treating them as inline. If the installed stage parser is unavailable, Kiro/Codex/OpenCode diff --git a/harness/kiro-ide/agents/aidlc-architect-agent.json b/harness/kiro-ide/agents/aidlc-architect-agent.json deleted file mode 100644 index 3a49adbae..000000000 --- a/harness/kiro-ide/agents/aidlc-architect-agent.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/aws/amazon-q-developer-cli/refs/heads/main/schemas/agent-v1.json", - "name": "aidlc-architect-agent", - "description": "AI-DLC Architect Agent \u2014 delegation target for the reverse-engineering (2.1) synthesis step. Use for delegated architecture-analysis tasks.", - "prompt": "file://aidlc-architect-agent.md", - "tools": [ - "fs_read", - "fs_write", - "execute_bash", - "thinking" - ], - "allowedTools": [ - "fs_read", - "thinking" - ], - "toolsSettings": { - "execute_bash": { - "allowedCommands": [ - "bun \\.kiro/tools/.*", - "date -u .*" - ] - }, - "fs_write": { - "allowedPaths": [ - "aidlc/spaces/**" - ] - } - }, - "resources": [ - "file://.kiro/agents/aidlc-architect-agent.md", - "file://.kiro/knowledge/aidlc-architect-agent/*.md", - "file://.kiro/knowledge/aidlc-shared/*.md", - "file://aidlc/spaces/default/memory/**/*.md" - ], - "hooks": {} -} diff --git a/harness/kiro-ide/agents/aidlc-architecture-reviewer-agent.json b/harness/kiro-ide/agents/aidlc-architecture-reviewer-agent.json deleted file mode 100644 index 947d6c81a..000000000 --- a/harness/kiro-ide/agents/aidlc-architecture-reviewer-agent.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/aws/amazon-q-developer-cli/refs/heads/main/schemas/agent-v1.json", - "name": "aidlc-architecture-reviewer-agent", - "description": "AI-DLC Architecture Reviewer — delegation target for reviewing design artifacts for soundness and implementability.", - "prompt": "file://aidlc-architecture-reviewer-agent.md", - "tools": ["fs_read", "fs_write", "execute_bash", "thinking"], - "allowedTools": ["fs_read", "fs_write", "thinking"], - "toolsSettings": { - "execute_bash": { - "allowedCommands": ["bun \\.kiro/tools/.*", "date -u .*"] - }, - "fs_write": { - "allowedPaths": ["aidlc/spaces/**"] - } - }, - "resources": [ - "file://.kiro/agents/aidlc-architecture-reviewer-agent.md", - "file://.kiro/knowledge/aidlc-architecture-reviewer-agent/*.md", - "file://.kiro/knowledge/aidlc-shared/*.md", - "file://aidlc/spaces/default/memory/**/*.md" - ], - "hooks": {} -} diff --git a/harness/kiro-ide/agents/aidlc-aws-platform-agent.json b/harness/kiro-ide/agents/aidlc-aws-platform-agent.json deleted file mode 100644 index 91b3d586c..000000000 --- a/harness/kiro-ide/agents/aidlc-aws-platform-agent.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/aws/amazon-q-developer-cli/refs/heads/main/schemas/agent-v1.json", - "name": "aidlc-aws-platform-agent", - "description": "AI-DLC AWS Platform Agent - delegation target for ensemble stages (AWS service selection, infrastructure, platform perspective).", - "prompt": "file://aidlc-aws-platform-agent.md", - "tools": [ - "fs_read", - "fs_write", - "execute_bash", - "thinking" - ], - "allowedTools": [ - "fs_read", - "thinking" - ], - "toolsSettings": { - "execute_bash": { - "allowedCommands": [ - "bun \\.kiro/tools/.*", - "date -u .*" - ] - }, - "fs_write": { - "allowedPaths": [ - "aidlc/spaces/**" - ] - } - }, - "resources": [ - "file://.kiro/agents/aidlc-aws-platform-agent.md", - "file://.kiro/knowledge/aidlc-aws-platform-agent/*.md", - "file://.kiro/knowledge/aidlc-shared/*.md", - "file://aidlc/spaces/default/memory/**/*.md" - ], - "hooks": {} -} diff --git a/harness/kiro-ide/agents/aidlc-compliance-agent.json b/harness/kiro-ide/agents/aidlc-compliance-agent.json deleted file mode 100644 index 208eb51af..000000000 --- a/harness/kiro-ide/agents/aidlc-compliance-agent.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/aws/amazon-q-developer-cli/refs/heads/main/schemas/agent-v1.json", - "name": "aidlc-compliance-agent", - "description": "AI-DLC Compliance Agent - delegation target for ensemble stages (regulatory, data-residency, audit perspective).", - "prompt": "file://aidlc-compliance-agent.md", - "tools": [ - "fs_read", - "fs_write", - "execute_bash", - "thinking" - ], - "allowedTools": [ - "fs_read", - "thinking" - ], - "toolsSettings": { - "execute_bash": { - "allowedCommands": [ - "bun \\.kiro/tools/.*", - "date -u .*" - ] - }, - "fs_write": { - "allowedPaths": [ - "aidlc/spaces/**" - ] - } - }, - "resources": [ - "file://.kiro/agents/aidlc-compliance-agent.md", - "file://.kiro/knowledge/aidlc-compliance-agent/*.md", - "file://.kiro/knowledge/aidlc-shared/*.md", - "file://aidlc/spaces/default/memory/**/*.md" - ], - "hooks": {} -} diff --git a/harness/kiro-ide/agents/aidlc-composer-agent.json b/harness/kiro-ide/agents/aidlc-composer-agent.json deleted file mode 100644 index a98f7970d..000000000 --- a/harness/kiro-ide/agents/aidlc-composer-agent.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/aws/amazon-q-developer-cli/refs/heads/main/schemas/agent-v1.json", - "name": "aidlc-composer-agent", - "description": "AI-DLC Composer Agent - delegation target for composing a workflow plan (front, report, or in-flight). Proposes the EXECUTE/SKIP grid; after human approval writes the composed scope data.", - "prompt": "file://aidlc-composer-agent.md", - "tools": [ - "fs_read", - "fs_write", - "execute_bash", - "thinking" - ], - "allowedTools": [ - "fs_read", - "thinking" - ], - "toolsSettings": { - "execute_bash": { - "allowedCommands": [ - "bun \\.kiro/tools/.*", - "date -u .*" - ] - }, - "fs_write": { - "allowedPaths": [ - ".kiro/scopes/**", - ".kiro/tools/data/scope-grid.json" - ] - } - }, - "resources": [ - "file://.kiro/agents/aidlc-composer-agent.md", - "file://.kiro/scopes/*.md", - "file://.kiro/knowledge/aidlc-shared/*.md", - "file://aidlc/spaces/default/memory/**/*.md" - ], - "hooks": {} -} diff --git a/harness/kiro-ide/agents/aidlc-delivery-agent.json b/harness/kiro-ide/agents/aidlc-delivery-agent.json deleted file mode 100644 index d193ddaed..000000000 --- a/harness/kiro-ide/agents/aidlc-delivery-agent.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/aws/amazon-q-developer-cli/refs/heads/main/schemas/agent-v1.json", - "name": "aidlc-delivery-agent", - "description": "AI-DLC Delivery Agent - delegation target for ensemble stages (delivery planning, sequencing, approval-handoff perspective).", - "prompt": "file://aidlc-delivery-agent.md", - "tools": [ - "fs_read", - "fs_write", - "execute_bash", - "thinking" - ], - "allowedTools": [ - "fs_read", - "thinking" - ], - "toolsSettings": { - "execute_bash": { - "allowedCommands": [ - "bun \\.kiro/tools/.*", - "date -u .*" - ] - }, - "fs_write": { - "allowedPaths": [ - "aidlc/spaces/**" - ] - } - }, - "resources": [ - "file://.kiro/agents/aidlc-delivery-agent.md", - "file://.kiro/knowledge/aidlc-delivery-agent/*.md", - "file://.kiro/knowledge/aidlc-shared/*.md", - "file://aidlc/spaces/default/memory/**/*.md" - ], - "hooks": {} -} diff --git a/harness/kiro-ide/agents/aidlc-design-agent.json b/harness/kiro-ide/agents/aidlc-design-agent.json deleted file mode 100644 index 42abfd443..000000000 --- a/harness/kiro-ide/agents/aidlc-design-agent.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/aws/amazon-q-developer-cli/refs/heads/main/schemas/agent-v1.json", - "name": "aidlc-design-agent", - "description": "AI-DLC Design Agent - delegation target for ensemble stages (UX/UI perspective: mockups, personas, user experience).", - "prompt": "file://aidlc-design-agent.md", - "tools": [ - "fs_read", - "fs_write", - "execute_bash", - "thinking" - ], - "allowedTools": [ - "fs_read", - "thinking" - ], - "toolsSettings": { - "execute_bash": { - "allowedCommands": [ - "bun \\.kiro/tools/.*", - "date -u .*" - ] - }, - "fs_write": { - "allowedPaths": [ - "aidlc/spaces/**" - ] - } - }, - "resources": [ - "file://.kiro/agents/aidlc-design-agent.md", - "file://.kiro/knowledge/aidlc-design-agent/*.md", - "file://.kiro/knowledge/aidlc-shared/*.md", - "file://aidlc/spaces/default/memory/**/*.md" - ], - "hooks": {} -} diff --git a/harness/kiro-ide/agents/aidlc-developer-agent.json b/harness/kiro-ide/agents/aidlc-developer-agent.json deleted file mode 100644 index 229dd972c..000000000 --- a/harness/kiro-ide/agents/aidlc-developer-agent.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/aws/amazon-q-developer-cli/refs/heads/main/schemas/agent-v1.json", - "name": "aidlc-developer-agent", - "description": "AI-DLC Developer Agent - delegation target for reverse-engineering (2.1), user-stories mob collaboration (2.4), code-generation (3.5), and swarm units. Use for delegated implementation tasks.", - "prompt": "file://aidlc-developer-agent.md", - "tools": [ - "fs_read", - "fs_write", - "execute_bash", - "thinking" - ], - "allowedTools": [ - "fs_read", - "thinking" - ], - "toolsSettings": { - "execute_bash": { - "allowedCommands": [ - "bun \\.kiro/tools/.*", - "date -u .*" - ] - }, - "fs_write": { - "allowedPaths": [ - "aidlc/spaces/**" - ] - } - }, - "resources": [ - "file://.kiro/agents/aidlc-developer-agent.md", - "file://.kiro/knowledge/aidlc-developer-agent/*.md", - "file://.kiro/knowledge/aidlc-shared/*.md", - "file://aidlc/spaces/default/memory/**/*.md" - ], - "hooks": {} -} diff --git a/harness/kiro-ide/agents/aidlc-devsecops-agent.json b/harness/kiro-ide/agents/aidlc-devsecops-agent.json deleted file mode 100644 index b223e66d0..000000000 --- a/harness/kiro-ide/agents/aidlc-devsecops-agent.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/aws/amazon-q-developer-cli/refs/heads/main/schemas/agent-v1.json", - "name": "aidlc-devsecops-agent", - "description": "AI-DLC DevSecOps Agent - delegation target for ensemble stages (security hardening, secrets, supply-chain perspective).", - "prompt": "file://aidlc-devsecops-agent.md", - "tools": [ - "fs_read", - "fs_write", - "execute_bash", - "thinking" - ], - "allowedTools": [ - "fs_read", - "thinking" - ], - "toolsSettings": { - "execute_bash": { - "allowedCommands": [ - "bun \\.kiro/tools/.*", - "date -u .*" - ] - }, - "fs_write": { - "allowedPaths": [ - "aidlc/spaces/**" - ] - } - }, - "resources": [ - "file://.kiro/agents/aidlc-devsecops-agent.md", - "file://.kiro/knowledge/aidlc-devsecops-agent/*.md", - "file://.kiro/knowledge/aidlc-shared/*.md", - "file://aidlc/spaces/default/memory/**/*.md" - ], - "hooks": {} -} diff --git a/harness/kiro-ide/agents/aidlc-operations-agent.json b/harness/kiro-ide/agents/aidlc-operations-agent.json deleted file mode 100644 index 79ac8a07e..000000000 --- a/harness/kiro-ide/agents/aidlc-operations-agent.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/aws/amazon-q-developer-cli/refs/heads/main/schemas/agent-v1.json", - "name": "aidlc-operations-agent", - "description": "AI-DLC Operations Agent - delegation target for ensemble stages (observability, incident response, operations perspective).", - "prompt": "file://aidlc-operations-agent.md", - "tools": [ - "fs_read", - "fs_write", - "execute_bash", - "thinking" - ], - "allowedTools": [ - "fs_read", - "thinking" - ], - "toolsSettings": { - "execute_bash": { - "allowedCommands": [ - "bun \\.kiro/tools/.*", - "date -u .*" - ] - }, - "fs_write": { - "allowedPaths": [ - "aidlc/spaces/**" - ] - } - }, - "resources": [ - "file://.kiro/agents/aidlc-operations-agent.md", - "file://.kiro/knowledge/aidlc-operations-agent/*.md", - "file://.kiro/knowledge/aidlc-shared/*.md", - "file://aidlc/spaces/default/memory/**/*.md" - ], - "hooks": {} -} diff --git a/harness/kiro-ide/agents/aidlc-pipeline-deploy-agent.json b/harness/kiro-ide/agents/aidlc-pipeline-deploy-agent.json deleted file mode 100644 index cd0f81b63..000000000 --- a/harness/kiro-ide/agents/aidlc-pipeline-deploy-agent.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/aws/amazon-q-developer-cli/refs/heads/main/schemas/agent-v1.json", - "name": "aidlc-pipeline-deploy-agent", - "description": "AI-DLC Pipeline & Deploy Agent - delegation target for ensemble stages (CI/CD, deployment pipeline perspective).", - "prompt": "file://aidlc-pipeline-deploy-agent.md", - "tools": [ - "fs_read", - "fs_write", - "execute_bash", - "thinking" - ], - "allowedTools": [ - "fs_read", - "thinking" - ], - "toolsSettings": { - "execute_bash": { - "allowedCommands": [ - "bun \\.kiro/tools/.*", - "date -u .*" - ] - }, - "fs_write": { - "allowedPaths": [ - "aidlc/spaces/**" - ] - } - }, - "resources": [ - "file://.kiro/agents/aidlc-pipeline-deploy-agent.md", - "file://.kiro/knowledge/aidlc-pipeline-deploy-agent/*.md", - "file://.kiro/knowledge/aidlc-shared/*.md", - "file://aidlc/spaces/default/memory/**/*.md" - ], - "hooks": {} -} diff --git a/harness/kiro-ide/agents/aidlc-product-agent.json b/harness/kiro-ide/agents/aidlc-product-agent.json deleted file mode 100644 index c8c57fc60..000000000 --- a/harness/kiro-ide/agents/aidlc-product-agent.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/aws/amazon-q-developer-cli/refs/heads/main/schemas/agent-v1.json", - "name": "aidlc-product-agent", - "description": "AI-DLC Product Agent - delegation target for ensemble stages (owner of intent capture, requirements, user stories; collaborator elsewhere).", - "prompt": "file://aidlc-product-agent.md", - "tools": [ - "fs_read", - "fs_write", - "execute_bash", - "thinking" - ], - "allowedTools": [ - "fs_read", - "thinking" - ], - "toolsSettings": { - "execute_bash": { - "allowedCommands": [ - "bun \\.kiro/tools/.*", - "date -u .*" - ] - }, - "fs_write": { - "allowedPaths": [ - "aidlc/spaces/**" - ] - } - }, - "resources": [ - "file://.kiro/agents/aidlc-product-agent.md", - "file://.kiro/knowledge/aidlc-product-agent/*.md", - "file://.kiro/knowledge/aidlc-shared/*.md", - "file://aidlc/spaces/default/memory/**/*.md" - ], - "hooks": {} -} diff --git a/harness/kiro-ide/agents/aidlc-product-lead-agent.json b/harness/kiro-ide/agents/aidlc-product-lead-agent.json deleted file mode 100644 index d1c8a8b89..000000000 --- a/harness/kiro-ide/agents/aidlc-product-lead-agent.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/aws/amazon-q-developer-cli/refs/heads/main/schemas/agent-v1.json", - "name": "aidlc-product-lead-agent", - "description": "AI-DLC Product Lead Reviewer — delegation target for reviewing requirements, user stories, and mockups.", - "prompt": "file://aidlc-product-lead-agent.md", - "tools": ["fs_read", "fs_write", "execute_bash", "thinking"], - "allowedTools": ["fs_read", "fs_write", "thinking"], - "toolsSettings": { - "execute_bash": { - "allowedCommands": ["bun \\.kiro/tools/.*", "date -u .*"] - }, - "fs_write": { - "allowedPaths": ["aidlc/spaces/**"] - } - }, - "resources": [ - "file://.kiro/agents/aidlc-product-lead-agent.md", - "file://.kiro/knowledge/aidlc-product-lead-agent/*.md", - "file://.kiro/knowledge/aidlc-shared/*.md", - "file://aidlc/spaces/default/memory/**/*.md" - ], - "hooks": {} -} diff --git a/harness/kiro-ide/agents/aidlc-quality-agent.json b/harness/kiro-ide/agents/aidlc-quality-agent.json deleted file mode 100644 index c61de8179..000000000 --- a/harness/kiro-ide/agents/aidlc-quality-agent.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/aws/amazon-q-developer-cli/refs/heads/main/schemas/agent-v1.json", - "name": "aidlc-quality-agent", - "description": "AI-DLC Quality Agent - delegation target for ensemble stages (test strategy, testability, quality-gate perspective).", - "prompt": "file://aidlc-quality-agent.md", - "tools": [ - "fs_read", - "fs_write", - "execute_bash", - "thinking" - ], - "allowedTools": [ - "fs_read", - "thinking" - ], - "toolsSettings": { - "execute_bash": { - "allowedCommands": [ - "bun \\.kiro/tools/.*", - "date -u .*" - ] - }, - "fs_write": { - "allowedPaths": [ - "aidlc/spaces/**" - ] - } - }, - "resources": [ - "file://.kiro/agents/aidlc-quality-agent.md", - "file://.kiro/knowledge/aidlc-quality-agent/*.md", - "file://.kiro/knowledge/aidlc-shared/*.md", - "file://aidlc/spaces/default/memory/**/*.md" - ], - "hooks": {} -} diff --git a/harness/kiro-ide/agents/aidlc.json b/harness/kiro-ide/agents/aidlc.json deleted file mode 100644 index 2061c3fe2..000000000 --- a/harness/kiro-ide/agents/aidlc.json +++ /dev/null @@ -1,61 +0,0 @@ -{ - "name": "aidlc", - "description": "AI-DLC conductor agent \u2014 run /aidlc to start or resume a workflow", - "prompt": "You are a software development assistant in a project that uses AI-DLC (AI-Driven Development Life Cycle). When the user invokes /aidlc (or asks to start, resume, or manage an AI-DLC workflow), follow the aidlc skill exactly \u2014 it defines the forwarding loop and the engine that owns all routing. CRITICAL forwarding rules, which override any instinct to make progress yourself: (1) The engine binary aidlc-orchestrate.ts is the ONLY authority on the next move \u2014 run it, do EXACTLY what its single directive says, then report; never re-derive routing. (2) Your VERY FIRST action: append everything the user typed after /aidlc to the first `next` call unchanged \u2014 `/aidlc --phase ideation` MUST become `next --phase ideation`, never a bare `next`; dropping --phase/--stage sends the workflow to the wrong stage and is a bug. (3) When a directive is a print whose message names a command to run (e.g. aidlc-jump.ts execute ...), run THAT EXACT command as your immediate next tool call \u2014 do NOT run `next` again or read more files until it has run. Skipping the named command silently breaks the workflow. Outside of AI-DLC workflows, assist normally.", - "tools": [ - "fs_read", - "fs_write", - "execute_bash", - "todo_list", - "thinking", - "subagent" - ], - "allowedTools": [ - "fs_read", - "thinking", - "todo_list" - ], - "toolsSettings": { - "execute_bash": { - "allowedCommands": [ - "bun \\.kiro/tools/.*", - "bun \\${?KIRO_PROJECT_DIR}?/\\.kiro/tools/.*", - "date -u .*" - ], - "deniedCommands": [ - "rm -rf /.*", - "git push .*" - ] - }, - "fs_write": { - "allowedPaths": [ - "aidlc/spaces/**", - ".kiro/sensors/**", - "aidlc/.aidlc-compose-pending" - ] - }, - "subagent": { - "trustedAgents": [ - "aidlc-developer-agent", - "aidlc-architect-agent", - "aidlc-architecture-reviewer-agent", - "aidlc-product-lead-agent", - "aidlc-composer-agent", - "aidlc-product-agent", - "aidlc-design-agent", - "aidlc-delivery-agent", - "aidlc-aws-platform-agent", - "aidlc-compliance-agent", - "aidlc-devsecops-agent", - "aidlc-quality-agent", - "aidlc-pipeline-deploy-agent", - "aidlc-operations-agent" - ] - } - }, - "resources": [ - "skill://.kiro/skills/*/SKILL.md", - "file://aidlc/spaces/default/memory/**/*.md", - "file://AGENTS.md" - ] -} diff --git a/harness/kiro-ide/agents/aidlc.md b/harness/kiro-ide/agents/aidlc.md new file mode 100644 index 000000000..d0e1421a3 --- /dev/null +++ b/harness/kiro-ide/agents/aidlc.md @@ -0,0 +1,25 @@ +--- +name: aidlc +description: AI-DLC conductor agent — run /aidlc to start or resume a workflow +tools: ["read", "write", "shell", "subagent"] +permissions: + rules: + - capability: shell + effect: allow + match: + - "bun {{HARNESS_DIR}}/tools/aidlc-*" + - "date -u *" + - capability: shell + effect: deny + match: + - "rm -rf *" + - "git push *" + - capability: filesystem + effect: allow + match: + - "aidlc/spaces/**" + - "{{HARNESS_DIR}}/sensors/**" + - "aidlc/.aidlc-compose-pending" +--- + +You are a software development assistant in a project that uses AI-DLC (AI-Driven Development Life Cycle). When the user invokes /aidlc (or asks to start, resume, or manage an AI-DLC workflow), follow the aidlc skill exactly — it defines the forwarding loop and the engine that owns all routing. CRITICAL forwarding rules, which override any instinct to make progress yourself: (1) The engine binary aidlc-orchestrate.ts is the ONLY authority on the next move — run it, do EXACTLY what its single directive says, then report; never re-derive routing. (2) Your VERY FIRST action: append everything the user typed after /aidlc to the first `next` call unchanged — `/aidlc --phase ideation` MUST become `next --phase ideation`, never a bare `next`; dropping --phase/--stage sends the workflow to the wrong stage and is a bug. (3) When a directive is a print whose message names a command to run (e.g. aidlc-jump.ts execute ...), run THAT EXACT command as your immediate next tool call — do NOT run `next` again or read more files until it has run. Skipping the named command silently breaks the workflow. Outside of AI-DLC workflows, assist normally. diff --git a/harness/kiro-ide/manifest.ts b/harness/kiro-ide/manifest.ts index ecc6530ca..92cf6b9a9 100644 --- a/harness/kiro-ide/manifest.ts +++ b/harness/kiro-ide/manifest.ts @@ -1,26 +1,88 @@ // harness/kiro-ide/manifest.ts — the Kiro IDE distribution row. // -// Identical to the Kiro CLI harness (harness/kiro/) EXCEPT: -// - Ships v2 hook JSON files (hooks/aidlc-*.json, the -// {"version":"v1","hooks":[...]} schema with PascalCase triggers) for hook -// registration on IDE >=1.0.1xx, plus legacy .kiro.hook files for pre-1.0 -// IDE builds (coexistence: no double-firing on any generation tested) -// - The aidlc.json agent config omits the `hooks` field (dead weight in IDE) -// - Injects a `tools:` frontmatter grant into the delegation-target agent -// .md files (frontmatterAdditions below) - the IDE resolves a delegated -// subagent's tools from the agent .md frontmatter, not from the agent-v1 -// JSON the CLI reads, so without the injected line an IDE delegate runs -// toolless (field-proven: the dispatched composer reported "terminal tool -// not available" until the grant was added). +// Kiro IDE 1.0 native format. Descends from the Kiro CLI harness (harness/kiro/) +// but drops the CLI surfaces the IDE does not read and adds the IDE-native ones: // -// The CLI harness relies on agent JSON hooks (the `hooks` object inside -// aidlc.json); the IDE harness relies on hooks/aidlc-*.json v2 hook files (the -// only mechanism current IDEs execute). Both share the same core and TS hook -// bodies; each ships its own adapter. +// - Agents ship as .md ONLY (the IDE resolves agents from Markdown frontmatter, +// not the CLI's agent-v1 JSON). The 15 agent JSONs the CLI tree ships are +// omitted here, along with settings/cli.json (CLI-only activation). +// - The conductor ships as an authored agents/aidlc.md so it appears in the +// IDE agent selector (the CLI's aidlc.json is not read by the IDE). +// - Each delegation-target agent .md gets a `tools:` grant AND a +// `permissions.rules` block (IDE 1.0's capability model), and drops the +// CLI-only `disallowedTools` field (frontmatterAdditions + frontmatterRemovals). +// - Hooks register via v2 JSON manifests (aidlc-*.json, "version":"v1") for +// IDE >=1.0.1xx, plus legacy .kiro.hook files for pre-1.0 coexistence (no +// double-firing on any generation tested). Unchanged by this row. +// +// The hook adapter and TS hook bodies stay byte-shared with every other harness. import type { HarnessManifest } from "../../scripts/manifest-types.ts"; import onboardingFills from "./onboarding.fills.ts"; +// The 14 delegation-target personas. All but the composer get the same lean +// grant (shell for the engine CLIs + write into their space); the composer +// additionally reaches the scope grid it authors. Declared once and expanded +// into frontmatterAdditions so the roster is a single list, not 14 stanzas. +const DELEGATION_AGENTS = [ + "aidlc-composer-agent", + "aidlc-developer-agent", + "aidlc-architect-agent", + "aidlc-product-lead-agent", + "aidlc-architecture-reviewer-agent", + "aidlc-product-agent", + "aidlc-design-agent", + "aidlc-delivery-agent", + "aidlc-aws-platform-agent", + "aidlc-compliance-agent", + "aidlc-devsecops-agent", + "aidlc-quality-agent", + "aidlc-pipeline-deploy-agent", + "aidlc-operations-agent", +] as const; + +// The filesystem allow-list differs for the composer (it writes the scope grid, +// not artifacts under a space). Everyone else writes into the active space. +// frontmatterAdditions are injected AFTER the {{HARNESS_DIR}} token transform, +// so the harness dir is written literally here (this row is .kiro-only). +const composerPaths = [` - ".kiro/scopes/**"`, ` - ".kiro/tools/data/scope-grid.json"`]; +const spacePaths = [` - "aidlc/spaces/**"`]; + +// tools: grant + permissions.rules block, appended to each persona .md during +// projection. The IDE 1.0 permission model is capability/effect/match; the +// grant is the IDE analogue of the CLI JSON's allowedTools + toolsSettings. +// +// SCOPE of the shell rule. The CLI JSON grants the regex `bun \.kiro/tools/.*`; +// the IDE matches GLOBS, so the equivalent is `bun .kiro/tools/aidlc-*`. The +// prefix is deliberately as narrow as the engine's real surface: every command a +// conductor or delegate issues is `bun .kiro/tools/aidlc-.ts ` (the +// eight referenced by the conductor prose today: orchestrate, state, log, +// utility, learnings, graph, swarm, worktree). A bare `bun *` would additionally +// pre-approve `bun -e ` and any workspace script — which can +// write outside the filesystem paths granted below — so it is not the faithful +// translation of the CLI grant. +// +// These rules are AUTOAPPROVALS, not a sandbox: Kiro defaults an unmatched +// operation to `ask`, not `deny`. So the lists decide what proceeds without a +// consent prompt; they do not bound where a delegate can ultimately write. +function personaFrontmatter(agent: string): string[] { + const fsPaths = agent === "aidlc-composer-agent" ? composerPaths : spacePaths; + return [ + `tools: ["read", "write", "shell"]`, + `permissions:`, + ` rules:`, + ` - capability: shell`, + ` effect: allow`, + ` match:`, + ` - "bun .kiro/tools/aidlc-*"`, + ` - "date -u *"`, + ` - capability: filesystem`, + ` effect: allow`, + ` match:`, + ...fsPaths, + ]; +} + const manifest: HarnessManifest = { name: "kiro-ide", harnessDir: ".kiro", @@ -40,28 +102,14 @@ const manifest: HarnessManifest = { { src: "skills/aidlc-outcomes-pack", dst: "skills/aidlc-outcomes-pack" }, ], - // Authored surfaces: same as CLI but adds the v2 hook JSON files and omits - // the hooks field from aidlc.json. + // Authored surfaces: the orchestrator skill, the conductor aidlc.md (IDE + // selector entry — the CLI's aidlc.json is not read by the IDE), the shared + // hook adapter, and the hook manifests. NO agent-v1 JSONs and NO + // settings/cli.json — those are CLI-only surfaces the IDE does not read. harnessFiles: [ { src: "skills/aidlc/SKILL.md", dst: "skills/aidlc/SKILL.md" }, { src: "skills/aidlc/question-rendering.md", dst: "skills/aidlc/question-rendering.md" }, - { src: "agents/aidlc.json", dst: "agents/aidlc.json" }, - { src: "agents/aidlc-architect-agent.json", dst: "agents/aidlc-architect-agent.json" }, - { src: "agents/aidlc-developer-agent.json", dst: "agents/aidlc-developer-agent.json" }, - { src: "agents/aidlc-product-lead-agent.json", dst: "agents/aidlc-product-lead-agent.json" }, - { src: "agents/aidlc-architecture-reviewer-agent.json", dst: "agents/aidlc-architecture-reviewer-agent.json" }, - { src: "agents/aidlc-composer-agent.json", dst: "agents/aidlc-composer-agent.json" }, - // Ensemble collaborator configs (2.5.0 roster closure): lean read+shell - // delegation targets so any stage can flip to an ensemble topology here. - { src: "agents/aidlc-product-agent.json", dst: "agents/aidlc-product-agent.json" }, - { src: "agents/aidlc-design-agent.json", dst: "agents/aidlc-design-agent.json" }, - { src: "agents/aidlc-delivery-agent.json", dst: "agents/aidlc-delivery-agent.json" }, - { src: "agents/aidlc-aws-platform-agent.json", dst: "agents/aidlc-aws-platform-agent.json" }, - { src: "agents/aidlc-compliance-agent.json", dst: "agents/aidlc-compliance-agent.json" }, - { src: "agents/aidlc-devsecops-agent.json", dst: "agents/aidlc-devsecops-agent.json" }, - { src: "agents/aidlc-quality-agent.json", dst: "agents/aidlc-quality-agent.json" }, - { src: "agents/aidlc-pipeline-deploy-agent.json", dst: "agents/aidlc-pipeline-deploy-agent.json" }, - { src: "agents/aidlc-operations-agent.json", dst: "agents/aidlc-operations-agent.json" }, + { src: "agents/aidlc.md", dst: "agents/aidlc.md" }, { src: "hooks/aidlc-kiro-adapter.ts", dst: "hooks/aidlc-kiro-adapter.ts" }, { src: "hooks/aidlc-audit-logger.json", dst: "hooks/aidlc-audit-logger.json" }, { src: "hooks/aidlc-mint.json", dst: "hooks/aidlc-mint.json" }, @@ -88,7 +136,6 @@ const manifest: HarnessManifest = { { src: "hooks/aidlc-session-start.kiro.hook", dst: "hooks/aidlc-session-start.kiro.hook" }, { src: "hooks/aidlc-stop.kiro.hook", dst: "hooks/aidlc-stop.kiro.hook" }, { src: "hooks/aidlc-sync-statusline.kiro.hook", dst: "hooks/aidlc-sync-statusline.kiro.hook" }, - { src: "settings/cli.json", dst: "settings/cli.json" }, // Project-root .gitignore (beside .kiro/, not inside it) — same workspace-layout // committed-vs-ignored split as the Kiro CLI tree: per-user cursors + machine-local // runtime ignored, the shared work (memory/codekb/registry/state/audit shards/ @@ -101,36 +148,30 @@ const manifest: HarnessManifest = { { src: "dot-gitignore", dst: ".gitignore", projectRoot: true }, ], - // IDE-native tool grants for the delegation targets (the agents the - // conductor dispatches via the `subagent` tool). The IDE reads these - // from the .md frontmatter; the agent-v1 JSONs above are CLI-only. Kiro IDE - // frontmatter tool names: "read" / "write" / "shell". NOTE the IDE grant is - // UNSCOPED (no allowedCommands/allowedPaths equivalent) - wider than the - // CLI JSON sandbox; the persona Boundaries prose and the conductor's gates - // remain the behavioral constraint. Reviewers need "write" too: the stage - // protocol has them append a `## Review` section to the primary artifact - // (the same grant their CLI JSONs carry). The nine ensemble collaborators - // (2.5.0 roster closure) also get write: the everyone-writes model has each - // collaborator author its own contribution file (stage-protocol §11); the - // contributions-dir-only bound is prose + the engine's ensemble evidence - // check, since IDE grants cannot express per-stage paths. Never grant a - // delegation tool here - delegates must not nest. - frontmatterAdditions: [ - { file: "agents/aidlc-composer-agent.md", lines: [`tools: ["read", "write", "shell"]`] }, - { file: "agents/aidlc-developer-agent.md", lines: [`tools: ["read", "write", "shell"]`] }, - { file: "agents/aidlc-architect-agent.md", lines: [`tools: ["read", "write", "shell"]`] }, - { file: "agents/aidlc-product-lead-agent.md", lines: [`tools: ["read", "write", "shell"]`] }, - { file: "agents/aidlc-architecture-reviewer-agent.md", lines: [`tools: ["read", "write", "shell"]`] }, - { file: "agents/aidlc-product-agent.md", lines: [`tools: ["read", "write", "shell"]`] }, - { file: "agents/aidlc-design-agent.md", lines: [`tools: ["read", "write", "shell"]`] }, - { file: "agents/aidlc-delivery-agent.md", lines: [`tools: ["read", "write", "shell"]`] }, - { file: "agents/aidlc-aws-platform-agent.md", lines: [`tools: ["read", "write", "shell"]`] }, - { file: "agents/aidlc-compliance-agent.md", lines: [`tools: ["read", "write", "shell"]`] }, - { file: "agents/aidlc-devsecops-agent.md", lines: [`tools: ["read", "write", "shell"]`] }, - { file: "agents/aidlc-quality-agent.md", lines: [`tools: ["read", "write", "shell"]`] }, - { file: "agents/aidlc-pipeline-deploy-agent.md", lines: [`tools: ["read", "write", "shell"]`] }, - { file: "agents/aidlc-operations-agent.md", lines: [`tools: ["read", "write", "shell"]`] }, - ], + // IDE-native frontmatter for the delegation targets (the agents the conductor + // dispatches via the `subagent` tool). The IDE reads a delegate's tool grant + // and permission rules from its .md frontmatter, not the CLI's agent-v1 JSON. + // `tools:` names the capability categories; `permissions.rules` is the IDE 1.0 + // capability/effect/match model (the analogue of the CLI JSON's allowedTools + + // toolsSettings autoapproval lists — see personaFrontmatter on why these grant + // consent-free operations rather than bound them). Reviewers get "write" too + // (they append a `## Review` section to the primary artifact); the ensemble + // collaborators get write to author their own contribution files. + // Never grant a delegation tool here — + // delegates must not nest. + frontmatterAdditions: DELEGATION_AGENTS.map((agent) => ({ + file: `agents/${agent}.md`, + lines: personaFrontmatter(agent), + })), + + // Drop the CLI-only `disallowedTools` field from each persona .md: the IDE + // expresses the no-nesting bound through the omitted `subagent` category in + // `tools:` above, not a disallowedTools list (a Claude Code / CLI field the + // IDE ignores). Removing it keeps the IDE frontmatter free of dead keys. + frontmatterRemovals: DELEGATION_AGENTS.map((agent) => ({ + file: `agents/${agent}.md`, + keys: ["disallowedTools"], + })), onboarding: { dst: "AGENTS.md", projectRoot: true, fills: onboardingFills }, diff --git a/harness/kiro-ide/onboarding.fills.ts b/harness/kiro-ide/onboarding.fills.ts index 8a563cba6..aae8b5e82 100644 --- a/harness/kiro-ide/onboarding.fills.ts +++ b/harness/kiro-ide/onboarding.fills.ts @@ -19,7 +19,7 @@ This project uses AI-DLC (AI-Driven Development Life Cycle) for structured devel prereq_bullets_tail: "", - agents_note: `On Kiro IDE the \`/aidlc\` command loads \`skills/aidlc/SKILL.md\` as the conductor. The full 14-persona roster supplies workers for the four dispatched stages (2.1 pipeline, 2.2 subagent, 2.4 mob, 3.5 subagent), reviewer passes, and composer requests through Markdown personas with IDE-native tool grants; the shipped agent-v1 JSON files and \`settings/cli.json\` are CLI-only compatibility surfaces and do not select an IDE default agent.`, + agents_note: `On Kiro IDE the \`/aidlc\` command loads \`skills/aidlc/SKILL.md\` as the conductor, and the conductor itself ships as \`agents/aidlc.md\` so it appears in the IDE agent selector. The full 14-persona roster supplies workers for the four dispatched stages (2.1 pipeline, 2.2 subagent, 2.4 mob, 3.5 subagent), reviewer passes, and composer requests through Markdown personas (\`agents/*.md\`) with IDE-native \`tools:\` grants and \`permissions.rules\`. The IDE resolves every agent from this Markdown frontmatter; no agent-v1 JSON or \`settings/cli.json\` ships here — those are Kiro CLI surfaces the IDE does not read.`, structure_extra: "", diff --git a/harness/kiro-ide/settings/cli.json b/harness/kiro-ide/settings/cli.json deleted file mode 100644 index c61e0e825..000000000 --- a/harness/kiro-ide/settings/cli.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "chat.defaultAgent": "aidlc", - "chat.modelDefaults": { - "claude-opus-4.8": { - "output_config": { - "effort": "xhigh" - } - } - } -} diff --git a/scripts/manifest-types.ts b/scripts/manifest-types.ts index 7e04711f6..6d28d7058 100644 --- a/scripts/manifest-types.ts +++ b/scripts/manifest-types.ts @@ -92,8 +92,28 @@ export type HarnessManifest = { * delegated subagent's tool grants from the agent .md frontmatter * (`tools: ["read", "write", "shell"]`), not from the CLI's agent-v1 * JSON - without the injected line an IDE delegate runs toolless. + * + * A block spanning multiple YAML lines is supported: the FIRST line names + * the key (validated + collision-checked), and any following indented + * continuation lines (leading whitespace) ride along untouched. This lets a + * nested mapping/sequence ship as one addition, e.g. the Kiro IDE 1.0 + * `permissions.rules` block: + * lines: ["permissions:", " rules:", " - capability: shell", ...]. */ frontmatterAdditions?: Array<{ file: string; lines: string[] }>; + /** + * Per-file YAML frontmatter KEYS removed from a core-projected .md's + * frontmatter - the inverse seam of frontmatterAdditions, for expressing the + * ABSENCE of a harness-neutral field in one harness without forking the core + * file. `file` is the harness-relative output path; `keys` are top-level + * frontmatter keys to drop (with their indented continuation lines). Example: + * the Kiro IDE ignores the CLI's `disallowedTools` field, so its distributions + * remove it rather than shipping dead frontmatter. The packager errors on an + * unmatched file (typo guard), a missing frontmatter block, and a key the core + * file does not declare (so a stale removal that no longer matches core is a + * loud no-op, never a silent miss). + */ + frontmatterRemovals?: Array<{ file: string; keys: string[] }>; /** * How to render this harness's onboarding doc from core/templates/onboarding.md. * null when the harness generates it elsewhere (codex, via emit) or ships none. @@ -131,3 +151,143 @@ export type HarnessManifest = { kind: "store" | "kiro"; }; }; + +// --- The frontmatter transformation seam ------------------------------- +// +// These two pure functions implement the frontmatterAdditions / +// frontmatterRemovals rows declared above. They live here, beside the contract +// they serve, so the transformation is unit-testable: scripts/package.ts runs +// its build at import time, so a test cannot reach into it for a function. +// Both are string-in/string-out and throw rather than emit questionable YAML. +// Append manifest-declared frontmatter lines to a projected .md, just before +// the closing `---` of its YAML block (manifest-types.ts frontmatterAdditions). +// Hard errors, never silent: the file must open with a frontmatter block, and +// no added line's key may already exist in it - if core later grows the same +// key, the build fails loudly instead of shipping a double. A multi-line block is +// supported: a line with NO leading whitespace opens a new key (validated + +// collision-checked); an indented continuation line (a nested mapping/sequence +// entry) rides along unchecked. +export function applyFrontmatterAdditions( + content: string, + lines: string[], + file: string, +): string { + const m = content.match(/^---\r?\n([\s\S]*?)\r?\n(---\r?\n)/); + if (!m) { + throw new Error( + `frontmatterAdditions: ${file} has no leading frontmatter block to extend.`, + ); + } + const fm = m[1]; + // Keys this addition block itself declares — a duplicate WITHIN the block is + // as invalid as one colliding with core, and silently ships a YAML mapping + // with a repeated key (last writer wins, or a parser error). + const added = new Set(); + for (const line of lines) { + // Indented lines continue the preceding key's block (nested mapping / + // sequence); only top-level lines name a key to validate. + if (/^\s/.test(line)) continue; + const key = line.split(":")[0]?.trim(); + if (!key || !/^[A-Za-z_][\w-]*$/.test(key)) { + throw new Error( + `frontmatterAdditions: line "${line}" for ${file} does not start with a YAML key.`, + ); + } + if (added.has(key)) { + throw new Error( + `frontmatterAdditions: ${file} declares "${key}:" twice in the same addition block - ` + + `emit one mapping per key.`, + ); + } + added.add(key); + if (new RegExp(`^${key}:`, "m").test(fm)) { + throw new Error( + `frontmatterAdditions: ${file} already declares "${key}:" in core - ` + + `resolve the collision instead of shipping a duplicate key.`, + ); + } + } + const insertAt = m[0].length - m[2].length; + return `${content.slice(0, insertAt)}${lines.join("\n")}\n${content.slice(insertAt)}`; +} + +// Remove manifest-declared frontmatter keys from a projected .md's YAML block +// (manifest-types.ts frontmatterRemovals) - the inverse of the additions seam, +// for a harness-neutral field a given harness must ship WITHOUT. A removed key +// drops its line plus any indented continuation lines (nested block). Hard +// errors, never silent: the file must open with a frontmatter block, and each +// named key must currently exist - a stale removal that no longer matches core +// fails loudly instead of silently no-opping. +export function applyFrontmatterRemovals( + content: string, + keys: string[], + file: string, +): string { + const m = content.match(/^---\r?\n([\s\S]*?)\r?\n(---\r?\n)/); + if (!m) { + throw new Error( + `frontmatterRemovals: ${file} has no leading frontmatter block to trim.`, + ); + } + const fmLines = m[1].split(/\r?\n/); + const keySet = new Set(keys); + const seen = new Set(); + const kept: string[] = []; + let dropping = false; + // Only a real top-level MAPPING KEY ends the block being dropped. A blank line + // or a full-line `#` comment is neither: treating those as terminators leaves + // the rest of the removed key's block behind as orphaned indented lines, which + // is invalid YAML (a mapping value with no key). + const TOP_LEVEL_KEY = /^([A-Za-z_][\w.-]*)\s*:/; + for (const line of fmLines) { + const indented = /^\s/.test(line); + const blankOrComment = line.trim() === "" || line.trimStart().startsWith("#"); + const keyMatch = indented ? null : TOP_LEVEL_KEY.exec(line); + if (keyMatch) { + // A top-level key ends any block being dropped and decides this line. + dropping = keySet.has(keyMatch[1]); + if (dropping) { + seen.add(keyMatch[1]); + continue; + } + } else if (dropping && (indented || blankOrComment)) { + // Still inside the removed key's block: its indented values, and the blank + // lines / comments interleaved among them, all go with it. + continue; + } else if (!indented && !blankOrComment) { + // A non-indented line that is not a mapping key (e.g. a list item at + // column 0, or a stray scalar). Fail closed rather than guess whether it + // belongs to the block being dropped. + throw new Error( + `frontmatterRemovals: ${file} frontmatter line is neither a top-level key ` + + `nor an indented continuation: ${JSON.stringify(line)}`, + ); + } + kept.push(line); + } + const missed = keys.filter((k) => !seen.has(k)); + if (missed.length > 0) { + throw new Error( + `frontmatterRemovals: ${file} does not declare key(s) [${missed.join(", ")}] in core - ` + + `remove the stale entry from the manifest.`, + ); + } + // Fail closed on a trailing orphan: if the last kept line is still an indented + // continuation of a removed key, the output would be invalid YAML. + const orphan = kept.findIndex((line, i) => { + if (!/^\s/.test(line)) return false; + for (let j = i - 1; j >= 0; j--) { + const prev = kept[j]; + if (prev.trim() === "" || prev.trimStart().startsWith("#")) continue; + return !TOP_LEVEL_KEY.test(prev) && !/^\s/.test(prev); + } + return true; // an indented line with no preceding key at all + }); + if (orphan >= 0) { + throw new Error( + `frontmatterRemovals: ${file} would emit an orphaned continuation line ` + + `(${JSON.stringify(kept[orphan])}) with no owning key.`, + ); + } + return `${content.slice(0, m.index ?? 0)}---\n${kept.join("\n")}\n${m[2]}${content.slice((m.index ?? 0) + m[0].length)}`; +} diff --git a/scripts/package.ts b/scripts/package.ts index c11935f03..c115bc7b4 100644 --- a/scripts/package.ts +++ b/scripts/package.ts @@ -50,6 +50,10 @@ import { dirname, isAbsolute, join, posix, relative, sep } from "node:path"; import { fileURLToPath } from "node:url"; import { spawnSync } from "node:child_process"; import type { HarnessManifest } from "./manifest-types.ts"; +import { + applyFrontmatterAdditions, + applyFrontmatterRemovals, +} from "./manifest-types.ts"; import { renderOnboarding } from "./onboarding.ts"; import { kiroModelDefaults, @@ -251,41 +255,6 @@ function transform( return content; } -// Append manifest-declared frontmatter lines to a projected .md, just before -// the closing `---` of its YAML block (manifest-types.ts frontmatterAdditions). -// Hard errors, never silent: the file must open with a frontmatter block, and -// no added line's key may already exist in it - if core later grows the same -// key, the build fails loudly instead of shipping a double. -function applyFrontmatterAdditions( - content: string, - lines: string[], - file: string, -): string { - const m = content.match(/^---\r?\n([\s\S]*?)\r?\n(---\r?\n)/); - if (!m) { - throw new Error( - `frontmatterAdditions: ${file} has no leading frontmatter block to extend.`, - ); - } - const fm = m[1]; - for (const line of lines) { - const key = line.split(":")[0]?.trim(); - if (!key || !/^[A-Za-z_][\w-]*$/.test(key)) { - throw new Error( - `frontmatterAdditions: line "${line}" for ${file} does not start with a YAML key.`, - ); - } - if (new RegExp(`^${key}:`, "m").test(fm)) { - throw new Error( - `frontmatterAdditions: ${file} already declares "${key}:" in core - ` + - `resolve the collision instead of shipping a duplicate key.`, - ); - } - } - const insertAt = m[0].length - m[2].length; - return `${content.slice(0, insertAt)}${lines.join("\n")}\n${content.slice(insertAt)}`; -} - function* walk(dir: string): Generator { for (const entry of readdirSync(dir).sort()) { const full = join(dir, entry); @@ -486,7 +455,11 @@ function buildTree(m: HarnessManifest, outRoot: string, seedFrom: string): strin const fmAdditions = new Map( (m.frontmatterAdditions ?? []).map(({ file, lines }) => [file, lines]), ); + const fmRemovals = new Map( + (m.frontmatterRemovals ?? []).map(({ file, keys }) => [file, keys]), + ); const fmApplied = new Set(); + const fmRemovalApplied = new Set(); for (const { src, dst } of m.coreDirs) { const srcDir = join(CORE_ROOT, src); if (!existsSync(srcDir)) continue; @@ -499,6 +472,16 @@ function buildTree(m: HarnessManifest, outRoot: string, seedFrom: string): strin // Manifest keys are POSIX; normalize the platform separator so the // lookup works on Windows too. const harnessRel = join(finalDst, rel).split(sep).join("/"); + // Removals run before additions: drop a harness-neutral key this harness + // omits (e.g. disallowedTools) before layering its own fields on top. + const fmDropKeys = fmRemovals.get(harnessRel); + if (fmDropKeys) { + out = Buffer.from( + applyFrontmatterRemovals(out.toString("utf-8"), fmDropKeys, harnessRel), + "utf-8", + ); + fmRemovalApplied.add(harnessRel); + } const fmLines = fmAdditions.get(harnessRel); if (fmLines) { out = Buffer.from( @@ -517,6 +500,13 @@ function buildTree(m: HarnessManifest, outRoot: string, seedFrom: string): strin `${fmMissed.join(", ")} - fix the path(s) in the manifest.`, ); } + const fmRemovalMissed = [...fmRemovals.keys()].filter((f) => !fmRemovalApplied.has(f)); + if (fmRemovalMissed.length > 0) { + throw new Error( + `[${m.name}] frontmatterRemovals name file(s) the core projection never produced: ` + + `${fmRemovalMissed.join(", ")} - fix the path(s) in the manifest.`, + ); + } // 2. Copy authored harness surfaces (token substitution on .md). projectRoot // files land beside the harness dir (e.g. dist/kiro/AGENTS.md), the rest diff --git a/scripts/plugin-hooks-template/compose.ts b/scripts/plugin-hooks-template/compose.ts index 9bfdfe4aa..1582acdb8 100644 --- a/scripts/plugin-hooks-template/compose.ts +++ b/scripts/plugin-hooks-template/compose.ts @@ -607,13 +607,51 @@ function pluginShipsViableOpencodeAgent(agent: string): boolean { return !collidingFile || collidingFile === join(nativeAgentsDir, `${agent}.md`); } -// Kiro, Codex, and OpenCode cannot dispatch a Markdown-only persona from the -// engine roster. Kiro requires BOTH a hand-authored agent-v1 JSON and conductor -// trustedAgents registration; Codex requires an agent config TOML; OpenCode -// requires a native `.opencode/agents/.md` subagent (installed, or viably -// shipped by this plugin — see pluginShipsViableOpencodeAgent). Reject any +// Kiro CLI, Codex, and OpenCode cannot dispatch a Markdown-only persona from the +// engine roster. Kiro CLI requires BOTH a hand-authored agent-v1 JSON and +// conductor trustedAgents registration; Codex requires an agent config TOML; +// OpenCode requires a native `.opencode/agents/.md` subagent (installed, or +// viably shipped by this plugin — see pluginShipsViableOpencodeAgent). Reject any // dispatched stage whose lead, support, or reviewer lacks that complete // surface. Markdown personas remain composable for accepted inline stages. +// +// KIRO CLI vs KIRO IDE. Both install under `.kiro`, so HARNESS_LEAF alone cannot +// tell them apart — the discriminator is the conductor's own shape: the CLI ships +// `agents/aidlc.json` (agent-v1, carrying the trustedAgents roster), while the IDE +// reads Markdown agents and ships `agents/aidlc.md` with no JSON at all. +// +// The IDE's dispatch surface is NOT "a Markdown persona exists". IDE 1.0 delegation +// needs a `tools:` grant AND a `permissions.rules` block on the target agent +// (harness/kiro-ide/manifest.ts:71-72 appends both to every core persona). A plugin +// agent ships neither, and compose applies no IDE projection when it copies one +// (unlike `.aidlc`, where projectOpencodeAgentMemory rewrites the twin). Copying it +// verbatim yields an agent that is dispatched but cannot read, write, or run +// anything — a silent capability hole, not support. +// +// So the IDE requirement is real, just different from the CLI's, and compose cannot +// satisfy it today: deciding which grants to inject is the packager's job +// (frontmatterAdditions), not the composer's. Until an IDE projection exists, the +// IDE follows the documented contract for every other harness whose surface a +// plugin cannot ship — REJECT the dispatched stage and drop-log it +// (docs/reference/18-plugin-mechanism.md). Rejecting is the honest state: it tells +// the plugin author the stage will not dispatch, instead of composing a stage that +// fails at runtime. +// Is an INSTALLED Kiro IDE agent `.md` actually dispatchable? IDE 1.0 delegation +// needs a `tools:` grant and a `permissions.rules` block; the packager appends both +// to every core persona (harness/kiro-ide/manifest.ts:71-72). A file that lacks +// them is dispatched with no capabilities, which is why existence alone is not the +// surface on this harness. Missing file → not dispatchable (same verdict). +function installedIdeAgentIsDispatchable(agentsDir: string, agent: string): boolean { + let content: string; + try { + content = readFileSync(join(agentsDir, `${agent}.md`), "utf-8"); + } catch { + return false; + } + const fm = frontmatter(content); + return /^tools:/m.test(fm) && /^permissions:/m.test(fm); +} + async function kiroPluginAgentPrechecks(): Promise { if ( HARNESS_LEAF !== ".kiro" && @@ -622,16 +660,26 @@ async function kiroPluginAgentPrechecks(): Promise(); - if (HARNESS_LEAF === ".kiro") { + if (isKiroCli) { try { const conductor = JSON.parse( readFileSync(join(HARNESS_DIR, "agents", "aidlc.json"), "utf-8"), @@ -657,11 +705,13 @@ async function kiroPluginAgentPrechecks(): Promise/memory/` (via `.claude/rules/aidlc.md` @-import stub) | `aidlc/spaces//memory/` (via Kiro resources glob) | `aidlc/spaces//memory/` (via Kiro resources glob) | `aidlc/spaces//memory/` (via `AIDLC_RULES_DIR`) | `aidlc/spaces//memory/` (via `instructions` glob) |", + "text": "| **Standing rules** (the layer chain) | `aidlc/spaces//memory/` (via `.claude/rules/aidlc.md` @-import stub) | `aidlc/spaces//memory/` (via Kiro resources glob) | `aidlc/spaces//memory/` (read directly from the seeded workspace shell) | `aidlc/spaces//memory/` (via `AIDLC_RULES_DIR`) | `aidlc/spaces//memory/` (via `instructions` glob) |", "why": "native-include mapping: names the .claude/rules/aidlc.md @-import stub that pulls the relocated memory tree (correct, not stale)" }, { diff --git a/tests/harness/harness-matrix.ts b/tests/harness/harness-matrix.ts index 6aa015031..299386f8b 100644 --- a/tests/harness/harness-matrix.ts +++ b/tests/harness/harness-matrix.ts @@ -27,7 +27,7 @@ type HarnessCapabilities = { manifestDir: string; wiringFile: string; }; - memoryInclude: "claude-import" | "codex-env" | "kiro-resources" | "opencode-instructions"; + memoryInclude: "claude-import" | "codex-env" | "kiro-resources" | "kiro-ide-workspace" | "opencode-instructions"; kiroAgentJson: boolean; ideAgentTools: boolean; reviewerScopeRegistration: ReviewerScopeRegistration; @@ -89,8 +89,8 @@ const HARNESS_CAPABILITIES = { manifestDir: ".kiro-plugin", wiringFile: "hooks/aidlc-plugin-compose.kiro.hook", }, - memoryInclude: "kiro-resources", - kiroAgentJson: true, + memoryInclude: "kiro-ide-workspace", + kiroAgentJson: false, ideAgentTools: true, reviewerScopeRegistration: "unsupported", }, @@ -218,6 +218,11 @@ function validateManifest( } if ( (capabilities.memoryInclude === "kiro-resources") !== hasKiroAgentJson || + // The Kiro IDE ships no agent JSON: the conductor is an authored + // agents/aidlc.md (IDE selector entry) and memory reaches the workflow via + // the workspace shell, not a CLI aidlc.json `resources:` surface. + (capabilities.memoryInclude === "kiro-ide-workspace") !== + manifest.harnessFiles.some((file) => file.dst === "agents/aidlc.md") || (capabilities.memoryInclude === "claude-import") !== manifest.harnessFiles.some((file) => file.dst === "rules/aidlc.md") || (capabilities.memoryInclude === "codex-env") !== diff --git a/tests/integration/t188-plugin-compose.test.ts b/tests/integration/t188-plugin-compose.test.ts index a959973b0..0e55c67ee 100644 --- a/tests/integration/t188-plugin-compose.test.ts +++ b/tests/integration/t188-plugin-compose.test.ts @@ -35,6 +35,9 @@ const PLUGIN = "test-pro"; const CLAUDE_DIST = join(REPO_ROOT, "dist", "claude", ".claude"); const OPENCODE_DIST = join(REPO_ROOT, "dist", "opencode"); const KIRO_DIST = join(REPO_ROOT, "dist", "kiro", ".kiro"); +// Kiro IDE installs under the same `.kiro` leaf as the CLI but ships Markdown +// agents and no agent-v1 JSON — the shape the dispatch precheck must recognise. +const KIRO_IDE_DIST = join(REPO_ROOT, "dist", "kiro-ide", ".kiro"); const CODEX_DIST = join(REPO_ROOT, "dist", "codex", ".codex"); const STAGE_TABLE_BEGIN = ""; @@ -502,20 +505,36 @@ describe("t188 plugin compose — emit + compose the contribution seam", () => { // --- Silent-failure seams (round-4): each must DROP-LOG, never silently no-op --- // Helper: compose a hand-built synthetic plugin into a fresh copy of the base // install, returning { drops, projectDir } so a test can assert on the drops. + // `install` selects WHICH dist seeds the fixture; `harnessLeaf` stays the env + // value the compose hook sees. They differ only for Kiro IDE, which installs + // under `.kiro` from its own dist — the case the CLI/IDE discriminator keys on. function composeSynthetic( name: string, files: Record, harnessLeaf: ".claude" | ".kiro" | ".codex" | ".aidlc" = ".claude", mutateInstall?: (proj: string, harnessDir: string) => void, + install: "claude" | "kiro" | "kiro-ide" | "codex" | "opencode" = harnessLeaf === ".kiro" + ? "kiro" + : harnessLeaf === ".codex" + ? "codex" + : harnessLeaf === ".aidlc" + ? "opencode" + : "claude", ): { drops: string; proj: string } { const proj = mkdtempSync(join(tmp, `syn-${name}-`)); - if (harnessLeaf === ".aidlc") { + if (install === "opencode") { // OpenCode's dist is a whole-project shape (.aidlc + .opencode + // opencode.json), unlike the single-dir harness dists. cpSync(OPENCODE_DIST, proj, { recursive: true }); } else { const baseDist = - harnessLeaf === ".kiro" ? KIRO_DIST : harnessLeaf === ".codex" ? CODEX_DIST : CLAUDE_DIST; + install === "kiro" + ? KIRO_DIST + : install === "kiro-ide" + ? KIRO_IDE_DIST + : install === "codex" + ? CODEX_DIST + : CLAUDE_DIST; cpSync(baseDist, join(proj, harnessLeaf), { recursive: true }); } const harnessDir = join(proj, harnessLeaf); @@ -618,6 +637,92 @@ describe("t188 plugin compose — emit + compose the contribution seam", () => { expect(drops).not.toContain('agent "aidlc-product-agent"'); }); + test("Kiro IDE rejects a plugin-dispatched stage — no IDE projection, so no dispatch surface (#555 §1)", () => { + // Same synthetic stage as the Kiro CLI case above, composed into a Kiro IDE + // install. Both installs live under `.kiro`, so the precheck keys on the + // conductor's shape (agents/aidlc.json present = CLI) rather than the harness + // leaf. The IDE requirement is real but different from the CLI's: delegation + // needs the agent's IDE 1.0 grants, which compose cannot inject into a plugin + // agent (deciding the grants is the packager's job). So the stage is rejected + // and drop-logged, per docs/reference/18-plugin-mechanism.md. + const stage = [ + "---", + "slug: syn-ide-ensemble", + "plugin: syn-ide", + "phase: inception", + "execution: ALWAYS", + "condition: always", + "lead_agent: aidlc-product-agent", + "support_agents:", + " - syn-ide-collaborator-agent", + "mode: mob", + "produces: []", + "consumes: []", + "requires_stage: []", + "inputs: x", + "outputs: y", + "---", + "", + "# Synthetic IDE Ensemble", + "", + "## Steps", + "body", + "", + ].join("\n"); + const agent = [ + "---", + "name: syn-ide-collaborator-agent", + "display_name: Synthetic IDE Collaborator", + "plugin: syn-ide", + "---", + "", + "# Synthetic IDE Collaborator", + "", + ].join("\n"); + const { drops, proj } = composeSynthetic( + "syn-ide", + { + "stages/inception/syn-ide-ensemble.md": stage, + "agents/syn-ide-collaborator-agent.md": agent, + }, + ".kiro", + undefined, + "kiro-ide", + ); + + // Precondition: this really is an IDE install (Markdown conductor, no JSON). + expect(existsSync(join(proj, ".kiro", "agents", "aidlc.md"))).toBe(true); + expect(existsSync(join(proj, ".kiro", "agents", "aidlc.json"))).toBe(false); + // The IDE's dispatch surface is the agent's GRANTS, not the file's existence: + // IDE 1.0 delegation needs `tools:` + `permissions.rules` (the packager appends + // both to every core persona). A plugin agent ships neither and compose applies + // no IDE projection, so the stage cannot dispatch and is rejected. + expect(existsSync(join( + proj, + ".kiro", + "aidlc-common", + "stages", + "inception", + "syn-ide-ensemble.md", + ))).toBe(false); + expect(drops).toContain('stage "syn-ide-ensemble"'); + expect(drops).toContain("syn-ide-collaborator-agent"); + expect(drops).toContain("permissions.rules"); + // Rejection is IDE-shaped: it must not advise the CLI's agent-v1 remedy. + expect(drops).not.toContain("agent-v1 JSON"); + expect(drops).not.toContain("toolsSettings.subagent.trustedAgents"); + + // Contrast — a core persona IS dispatchable on the IDE because the shipped + // roster carries the grants. Same harness, same compose: the verdict tracks + // the surface, not the harness leaf. + const corePersona = readFileSync( + join(proj, ".kiro", "agents", "aidlc-product-agent.md"), + "utf-8", + ); + expect(corePersona).toMatch(/^tools:/m); + expect(corePersona).toMatch(/^permissions:/m); + }); + test("Kiro rejects an agent JSON that is missing conductor trust registration", () => { const stage = [ "---", diff --git a/tests/smoke/t148-kiro-file-structure.test.ts b/tests/smoke/t148-kiro-file-structure.test.ts index f915150f0..ddeaf0bd6 100644 --- a/tests/smoke/t148-kiro-file-structure.test.ts +++ b/tests/smoke/t148-kiro-file-structure.test.ts @@ -136,42 +136,51 @@ describe("t148 dist/kiro file structure", () => { ).toBe(true); }); - test("every dispatched graph writer has a space-scoped write grant on Kiro CLI and IDE", () => { - for (const harness of ["kiro", "kiro-ide"] as const) { - const agentsDir = join(REPO_ROOT, "dist", harness, ".kiro", "agents"); - const writers = dispatchedSpaceWriters(harness); - expect(writers.length).toBeGreaterThan(0); - for (const agent of writers) { - const config = readJson(join(agentsDir, `${agent}.json`)); - expect(config.tools as string[]).toContain("fs_write"); - const settings = config.toolsSettings as Record; - expect(settings.fs_write?.allowedPaths).toContain("aidlc/spaces/**"); - } + test("every dispatched graph writer has a space write grant on Kiro CLI (JSON) and IDE (md permissions)", () => { + // Kiro CLI expresses the write grant in the agent-v1 JSON (tools + + // toolsSettings.allowedPaths); Kiro IDE expresses it in the agent .md + // frontmatter (tools: + permissions.rules), since the IDE ships no agent + // JSON. Both must name aidlc/spaces/** for every dispatched writer. + // + // These lists are AUTOAPPROVALS, not sandboxes: an unmatched operation + // defaults to `ask`, so naming the space path is what lets a delegate write + // its artifacts without a consent prompt — it does not prevent a write + // elsewhere. The assertion is therefore "the grant is present", not "writes + // are confined". + const cliDir = join(REPO_ROOT, "dist", "kiro", ".kiro", "agents"); + const cliWriters = dispatchedSpaceWriters("kiro"); + expect(cliWriters.length).toBeGreaterThan(0); + for (const agent of cliWriters) { + const config = readJson(join(cliDir, `${agent}.json`)); + expect(config.tools as string[]).toContain("fs_write"); + const settings = config.toolsSettings as Record; + expect(settings.fs_write?.allowedPaths).toContain("aidlc/spaces/**"); + } + const ideDir = join(REPO_ROOT, "dist", "kiro-ide", ".kiro", "agents"); + const ideWriters = dispatchedSpaceWriters("kiro-ide"); + expect(ideWriters.length).toBeGreaterThan(0); + for (const agent of ideWriters) { + const md = readFileSync(join(ideDir, `${agent}.md`), "utf-8"); + const fm = /^---\r?\n([\s\S]*?)\r?\n---/.exec(md)?.[1] ?? ""; + // tools: grants write; permissions.rules names the space path as a + // filesystem autoapproval (the composer additionally reaches the scope + // grid, so match the shared space path every writer carries). + expect(fm).toContain(`"write"`); + expect(fm).toContain(`"aidlc/spaces/**"`); } }); - test("shared Kiro CLI and IDE agent JSON sources remain byte-identical", () => { - const cliDir = join(REPO_ROOT, "harness", "kiro", "agents"); - const ideDir = join(REPO_ROOT, "harness", "kiro-ide", "agents"); - const intentionalReviewerDifferences = new Set([ - "aidlc-architecture-reviewer-agent.json", - "aidlc-product-lead-agent.json", - ]); - const shared = readdirSync(cliDir) - .filter((name) => name.endsWith("-agent.json")) - .filter((name) => !intentionalReviewerDifferences.has(name)) - .sort(); - expect( - readdirSync(ideDir) - .filter((name) => name.endsWith("-agent.json")) - .filter((name) => !intentionalReviewerDifferences.has(name)) - .sort(), - ).toEqual(shared); - for (const name of shared) { - expect(readFileSync(join(ideDir, name), "utf-8")).toBe( - readFileSync(join(cliDir, name), "utf-8"), - ); - } + test("Kiro IDE ships NO agent JSON — agents resolve from Markdown only (#555 §1)", () => { + // The IDE reads agents from .md frontmatter, not the CLI's agent-v1 JSON. + // The kiro-ide tree therefore ships zero agent .json (persona or conductor); + // the CLI tree keeps its full JSON roster. This is the §1 shape. + const ideDir = join(REPO_ROOT, "dist", "kiro-ide", ".kiro", "agents"); + expect(readdirSync(ideDir).filter((n) => n.endsWith(".json"))).toEqual([]); + // The conductor ships as an authored aidlc.md (IDE selector entry). + expect(existsSync(join(ideDir, "aidlc.md"))).toBe(true); + // The CLI tree is unaffected — its JSON roster still ships. + const cliDir = join(REPO_ROOT, "dist", "kiro", ".kiro", "agents"); + expect(readdirSync(cliDir).filter((n) => n.endsWith(".json")).length).toBeGreaterThanOrEqual(14); }); test("IDE-native tools: frontmatter grant on delegation targets - kiro-ide ONLY", () => { @@ -183,34 +192,36 @@ describe("t148 dist/kiro file structure", () => { // agents (on Claude a `tools:` frontmatter field would RESTRICT the // agent to non-Claude tool names, breaking it). const IDE_AGENTS = join(REPO_ROOT, "dist", "kiro-ide", ".kiro", "agents"); + // The IDE tree ships no agent JSON, so derive the delegation-target roster + // from the CLI (kiro) JSONs — the same hand-authored set (minus the + // conductor aidlc.json). A future delegate added without an IDE grant reds + // here instead of shipping toolless (the original field bug). + const CLI_AGENTS = join(REPO_ROOT, "dist", "kiro", ".kiro", "agents"); + const fmBlockOf = (p: string): string => + /^---\r?\n([\s\S]*?)\r?\n---/.exec(readFileSync(p, "utf-8"))?.[1] ?? ""; const fmToolsOf = (p: string): string | undefined => - /^tools:\s*(.+)$/m.exec( - /^---\r?\n([\s\S]*?)\r?\n---/.exec(readFileSync(p, "utf-8"))?.[1] ?? "", - )?.[1]; - // The delegation-target roster IS the set of hand-authored agent JSONs - // (minus the conductor aidlc.json) - derive it from disk so a future - // delegate added without a grant reds here instead of shipping toolless - // (the original field bug). Every delegate carries fs_write in its CLI - // JSON (builders author artifacts; reviewers append `## Review` per 12a; - // ensemble collaborators (2.5.0) write their own contribution files per - // stage-protocol §11 - everyone writes, the lead owns the produces[] - // artifacts), so every delegate's IDE grant is read+write+shell. The - // grant is still DERIVED from the CLI JSON rather than hardcoded, so a - // future read-only delegate stays expressible. Every NON-delegate - // kiro-ide agent must have NO grant (catches the injection landing on - // the wrong file). - const delegates = readdirSync(IDE_AGENTS) + /^tools:\s*(.+)$/m.exec(fmBlockOf(p))?.[1]; + const delegates = readdirSync(CLI_AGENTS) .filter((n) => n.endsWith("-agent.json")) .map((n) => n.replace(/\.json$/, ".md")); expect(delegates.length).toBeGreaterThanOrEqual(14); for (const f of readdirSync(IDE_AGENTS).filter((n) => n.endsWith(".md"))) { if (delegates.includes(f)) { - const cliJson = readJson(join(IDE_AGENTS, f.replace(/\.md$/, ".json"))); + // Every delegate carries fs_write in its CLI JSON (builders author + // artifacts; reviewers append `## Review` per 12a; ensemble + // collaborators write their own contribution files per §11), so every + // delegate's IDE grant is read+write+shell PLUS a permissions.rules + // block scoping filesystem to the space it writes. + const cliJson = readJson(join(CLI_AGENTS, f.replace(/\.md$/, ".json"))); const writes = ((cliJson.tools as string[]) ?? []).includes("fs_write"); - expect(fmToolsOf(join(IDE_AGENTS, f))).toBe( - writes ? `["read", "write", "shell"]` : `["read", "shell"]`, - ); + expect(writes, `${f}: expected a writing delegate`).toBe(true); + expect(fmToolsOf(join(IDE_AGENTS, f))).toBe(`["read", "write", "shell"]`); + expect(fmBlockOf(join(IDE_AGENTS, f))).toContain("permissions:"); } else { + // The conductor aidlc.md carries its own authored grant; every OTHER + // non-delegate kiro-ide agent must have NO injected grant (catches the + // injection landing on the wrong file). + if (f === "aidlc.md") continue; expect(fmToolsOf(join(IDE_AGENTS, f))).toBeUndefined(); } } diff --git a/tests/unit/t-active-space-includes.test.ts b/tests/unit/t-active-space-includes.test.ts index 76fb49d8a..4ba5de3a9 100644 --- a/tests/unit/t-active-space-includes.test.ts +++ b/tests/unit/t-active-space-includes.test.ts @@ -197,30 +197,36 @@ describe("t-active-space-includes: Kiro IDE resources follow the active space", process.env.AIDLC_HARNESS_DIR = ".kiro"; }); - test("re-points every IDE agent JSON memory glob while preserving the remaining config", () => { + test("re-point is a no-op on Kiro IDE — no agent JSON resources glob to follow (#555 §1)", () => { + // The Kiro IDE ships no agent JSON, so there is no per-space include to + // rewrite: repointHarnessIncludes finds no agents/*.json and returns an + // empty write list, leaving the authored .md surfaces byte-identical. + // + // This is a no-op, NOT a lost capability. `resources:` is a Kiro CLI + // agent-v1 key that the IDE agent schema does not define, so the memory glob + // the JSON carried was inert on this harness even before the JSON was + // dropped — re-pointing it changed nothing an IDE session could observe. + // The method reaches an IDE workflow through the engine's resolved + // `rules_in_context` (and its injected contents), which is the same channel + // on every harness. The active-space cursor still governs the surfaces that + // genuinely follow it: memoryDirFor() writers and the templates sensor (the + // PROJECT family in aidlc-graph.ts), asserted by the other tests here. const root = freshRoot(); seedSpaces(root); const agentsSrc = distSurface("kiro-ide", ".kiro", "agents"); const agentsDst = join(root, ".kiro", "agents"); mkdirSync(agentsDst, { recursive: true }); - const agentFiles = readdirSync(agentsSrc).filter((name) => name.endsWith(".json")).sort(); + const agentFiles = readdirSync(agentsSrc).sort(); for (const name of agentFiles) cpSync(join(agentsSrc, name), join(agentsDst, name)); + // The IDE tree ships zero agent JSON (§1). + expect(agentFiles.filter((n) => n.endsWith(".json"))).toHaveLength(0); - const conductorPath = join(agentsDst, "aidlc.json"); - const before = JSON.parse(readFileSync(conductorPath, "utf-8")) as { - resources: string[]; - [key: string]: unknown; - }; + const conductorMd = join(agentsDst, "aidlc.md"); + const before = readFileSync(conductorMd, "utf-8"); const written = repointHarnessIncludes(root, "teamB"); - expect(written).toHaveLength(agentFiles.length); - - const after = JSON.parse(readFileSync(conductorPath, "utf-8")) as { - resources: string[]; - [key: string]: unknown; - }; - expect(after.resources).toContain("file://aidlc/spaces/teamB/memory/**/*.md"); - expect(after.resources.some((resource) => resource.includes("/default/memory/"))).toBe(false); - expect({ ...after, resources: before.resources }).toEqual(before); + expect(written).toHaveLength(0); + // The authored conductor .md is untouched by a space switch. + expect(readFileSync(conductorMd, "utf-8")).toBe(before); }); }); diff --git a/tests/unit/t157-workspace-shell-seed.test.ts b/tests/unit/t157-workspace-shell-seed.test.ts index c4b4984bf..f555b887e 100644 --- a/tests/unit/t157-workspace-shell-seed.test.ts +++ b/tests/unit/t157-workspace-shell-seed.test.ts @@ -136,6 +136,22 @@ describe("t157 seeded workspace shell + re-rooted .gitignore (SEED)", () => { const config = readFileSync(join(harness.engineRoot, "config.toml"), "utf-8"); expect(config).toContain('AIDLC_RULES_DIR = "aidlc/spaces/default/memory"'); expect(existsSync(harness.onboardingDist)).toBe(true); + } else if (harness.capabilities.memoryInclude === "kiro-ide-workspace") { + // Kiro IDE has no agent-side preload surface for the method: the IDE + // agent schema is `name`/`description`/`tools`/`model`/`mcpServers`/ + // `permissions` — `resources:` is a Kiro CLI agent-v1 key the IDE does + // not read, so the CLI's memory glob never applied here even while the + // JSON shipped. The method reaches the workflow through the engine + // instead: `rules_in_context` names each resolved rule file and (since + // the rules_content injection) the directive carries their contents. + // What the shell must therefore provide is the seeded memory tree itself + // on disk for the engine to resolve against, alongside the auto-read + // project-root AGENTS.md. + expect( + existsSync(join(harness.distRoot, "aidlc", "spaces", "default", "memory", "org.md")), + harness.name, + ).toBe(true); + expect(existsSync(harness.onboardingDist)).toBe(true); } else { // opencode: the instructions glob in the project-root opencode.json is // the native include surface; AGENTS.md is the auto-read rules file. diff --git a/tests/unit/t220-tier-projection-module.test.ts b/tests/unit/t220-tier-projection-module.test.ts index 62a90f210..998b6dec2 100644 --- a/tests/unit/t220-tier-projection-module.test.ts +++ b/tests/unit/t220-tier-projection-module.test.ts @@ -337,7 +337,9 @@ describe("t220 shipped projection bytes (codex TOML, kiro JSON + md)", () => { }); test("kiro cli.json modelDefaults: authored conditional entries only, no tier-derived pins", () => { - for (const harness of ["kiro", "kiro-ide"]) { + // settings/cli.json is a Kiro CLI activation surface; the Kiro IDE ships no + // cli.json (it activates via the agent selector), so only the CLI tree here. + for (const harness of ["kiro"]) { const s = JSON.parse( readFileSync(dist(harness, ".kiro", "settings", "cli.json"), "utf-8"), ) as Record>; diff --git a/tests/unit/t239-documentation-parity.test.ts b/tests/unit/t239-documentation-parity.test.ts index cbe02b2a6..dc17e3584 100644 --- a/tests/unit/t239-documentation-parity.test.ts +++ b/tests/unit/t239-documentation-parity.test.ts @@ -246,18 +246,19 @@ describe("documentation parity derives current behavior from authored implementa expect(ideCell("Agent personas")).toContain("`tools:` grants"); expect(ideCell("Agent personas")).not.toContain("agent configs"); - expect(ideCell("Standing rules")).toContain("resources glob"); - expect(ideCell("Standing rules")).not.toContain("`rules_in_context`"); + expect(ideCell("Standing rules")).toContain("workspace shell"); + expect(ideCell("Standing rules")).not.toContain("resources glob"); expect(ideCell("Permissions / config")).toContain("`tools:` frontmatter"); expect(ideCell("Permissions / config")).not.toContain("settings/cli.json"); - const ideAgent = JSON.parse( - read("harness", "kiro-ide", "agents", "aidlc.json"), - ) as { resources?: string[] }; - expect(ideAgent.resources).toContain("file://aidlc/spaces/default/memory/**/*.md"); - const includesSource = read("core", "tools", "aidlc-includes.ts"); - expect(includesSource).toContain('if (harness === ".kiro")'); - expect(includesSource).toContain("repointKiroAgentResources"); + // The IDE conductor ships as authored Markdown (the CLI's aidlc.json is not + // read by the IDE). It carries no `resources:` glob — standing rules reach + // the workflow from the seeded workspace shell the IDE reads directly, not + // from an agent-embedded memory glob the way the Kiro CLI harness does. + const ideConductor = read("harness", "kiro-ide", "agents", "aidlc.md"); + expect(ideConductor).toContain("name: aidlc"); + expect(ideConductor).not.toMatch(/^resources:/m); + expect(existsSync(at("harness", "kiro-ide", "agents", "aidlc.json"))).toBe(false); }); test("documented agent roster matches agent files and reviewer frontmatter", () => { diff --git a/tests/unit/t249-frontmatter-seam.test.ts b/tests/unit/t249-frontmatter-seam.test.ts new file mode 100644 index 000000000..20ceb2379 --- /dev/null +++ b/tests/unit/t249-frontmatter-seam.test.ts @@ -0,0 +1,252 @@ +// covers: file:scripts/manifest-types.ts +// +// t249 — the frontmatter transformation seam (`frontmatterAdditions` / +// `frontmatterRemovals`). Mechanism: none (pure string in / string out; zero +// spawn, zero LLM). +// +// WHY THIS EXISTS. Both functions rewrite YAML that then ships in every +// projected agent file, and both are generic: any harness manifest can declare +// any key. A silent mis-transformation produces frontmatter that a harness +// parses differently than intended — or refuses — and the drift guard cannot +// catch it, because the drift guard only proves dist matches what the packager +// produced, not that what it produced is valid. So the contract these tests pin +// is FAIL CLOSED: on anything ambiguous, throw rather than emit questionable +// YAML. +// +// The two defects these guard against, both reproducible before the fix: +// 1. A blank line or a full-line comment inside the block being REMOVED used +// to terminate the removal, leaving the rest of that key's indented values +// behind as orphans — a mapping value with no key, i.e. invalid YAML. +// 2. An ADDITION block could declare the same top-level key twice; only +// collisions against the core file were checked, not within the block. + +import { describe, expect, test } from "bun:test"; +import { + applyFrontmatterAdditions, + applyFrontmatterRemovals, +} from "../../scripts/manifest-types.ts"; + +/** The frontmatter block of a projected file, without the fences. */ +function fmOf(content: string): string { + const m = /^---\r?\n([\s\S]*?)\r?\n---/.exec(content); + if (!m) throw new Error("no frontmatter block"); + return m[1]; +} + +/** Top-level keys, in order, as a YAML reader would see them. */ +function topLevelKeys(fm: string): string[] { + return fm + .split("\n") + .filter((line) => /^[A-Za-z_][\w.-]*\s*:/.test(line)) + .map((line) => line.split(":")[0].trim()); +} + +/** No indented line may appear before its owning top-level key. */ +function hasOrphanContinuation(fm: string): boolean { + let sawKey = false; + for (const line of fm.split("\n")) { + if (line.trim() === "" || line.trimStart().startsWith("#")) continue; + if (/^\s/.test(line)) { + if (!sawKey) return true; + continue; + } + sawKey = /^[A-Za-z_][\w.-]*\s*:/.test(line); + if (!sawKey) return true; // a non-indented line that is not a key + } + return false; +} + +const FILE = "agents/aidlc-developer-agent.md"; + +describe("t249 frontmatterRemovals", () => { + test("1: drops a scalar key and leaves every other line byte-identical", () => { + const src = ['---', 'name: dev', 'disallowedTools: Task', 'tools: ["read"]', '---', 'body', ''].join("\n"); + const out = applyFrontmatterRemovals(src, ["disallowedTools"], FILE); + expect(topLevelKeys(fmOf(out))).toEqual(["name", "tools"]); + expect(out).toContain('tools: ["read"]'); + expect(out.endsWith("body\n")).toBe(true); + }); + + test("2: drops a multi-line sequence block with all of its entries", () => { + const src = [ + "---", + "name: dev", + "disallowedTools:", + " - Task", + " - Other", + 'tools: ["read"]', + "---", + "body", + "", + ].join("\n"); + const out = applyFrontmatterRemovals(src, ["disallowedTools"], FILE); + expect(topLevelKeys(fmOf(out))).toEqual(["name", "tools"]); + expect(out).not.toContain("Task"); + expect(out).not.toContain("Other"); + expect(hasOrphanContinuation(fmOf(out))).toBe(false); + }); + + // === the defect: interleaved blanks / comments used to end the removal ===== + test("3: a blank line inside the removed block does NOT end the removal", () => { + const src = [ + "---", + "name: dev", + "disallowedTools:", + " - Task", + "", + " - Other", + 'tools: ["read"]', + "---", + "body", + "", + ].join("\n"); + const out = applyFrontmatterRemovals(src, ["disallowedTools"], FILE); + // Before the fix this emitted an orphaned ` - Other` under `name:`. + expect(out).not.toContain("Other"); + expect(hasOrphanContinuation(fmOf(out))).toBe(false); + expect(topLevelKeys(fmOf(out))).toEqual(["name", "tools"]); + }); + + test("4: a full-line comment inside the removed block goes with it", () => { + const src = [ + "---", + "name: dev", + "disallowedTools:", + " # the CLI-only denylist", + " - Task", + 'tools: ["read"]', + "---", + "body", + "", + ].join("\n"); + const out = applyFrontmatterRemovals(src, ["disallowedTools"], FILE); + expect(out).not.toContain("CLI-only denylist"); + expect(out).not.toContain("Task"); + expect(hasOrphanContinuation(fmOf(out))).toBe(false); + }); + + test("5: a comment BETWEEN two kept keys survives, attached to nothing removed", () => { + const src = [ + "---", + "name: dev", + "# a note about tools", + 'tools: ["read"]', + "disallowedTools: Task", + "---", + "body", + "", + ].join("\n"); + const out = applyFrontmatterRemovals(src, ["disallowedTools"], FILE); + expect(out).toContain("# a note about tools"); + expect(topLevelKeys(fmOf(out))).toEqual(["name", "tools"]); + }); + + // === fail-closed guards =================================================== + test("6: a declared key that the file does not carry is a hard error", () => { + const src = ["---", "name: dev", "---", "body", ""].join("\n"); + expect(() => applyFrontmatterRemovals(src, ["disallowedTools"], FILE)).toThrow( + /does not declare key\(s\) \[disallowedTools\]/, + ); + }); + + test("7: a file with no frontmatter block is a hard error", () => { + expect(() => applyFrontmatterRemovals("# just prose\n", ["x"], FILE)).toThrow( + /no leading frontmatter block/, + ); + }); + + test("8: a non-indented line that is not a mapping key fails closed", () => { + // A column-0 sequence entry is ambiguous — it could belong to the block being + // removed or to the preceding kept key. Guessing risks emitting invalid YAML. + const src = [ + "---", + "disallowedTools:", + "- Task", + "name: dev", + "---", + "body", + "", + ].join("\n"); + expect(() => applyFrontmatterRemovals(src, ["disallowedTools"], FILE)).toThrow( + /neither a top-level key nor an indented continuation/, + ); + }); +}); + +describe("t249 frontmatterAdditions", () => { + test("9: appends a multi-line block just before the closing fence", () => { + const src = ["---", "name: dev", "---", "body", ""].join("\n"); + const out = applyFrontmatterAdditions( + src, + ['tools: ["read", "write"]', "permissions:", " rules:", " - capability: shell"], + FILE, + ); + expect(topLevelKeys(fmOf(out))).toEqual(["name", "tools", "permissions"]); + expect(hasOrphanContinuation(fmOf(out))).toBe(false); + // The body is untouched and the fence order is preserved. + expect(out.endsWith("body\n")).toBe(true); + expect(fmOf(out).split("\n").at(-1)).toBe(" - capability: shell"); + }); + + test("10: a key already present in the file is a hard error", () => { + const src = ["---", "name: dev", 'tools: ["read"]', "---", "body", ""].join("\n"); + expect(() => applyFrontmatterAdditions(src, ['tools: ["write"]'], FILE)).toThrow( + /already declares "tools:" in core/, + ); + }); + + // === the defect: a duplicate WITHIN the addition block used to pass ======== + test("11: the same key twice in one addition block is a hard error", () => { + const src = ["---", "name: dev", "---", "body", ""].join("\n"); + expect(() => + applyFrontmatterAdditions(src, ['tools: ["read"]', "permissions:", " rules: []", 'tools: ["write"]'], FILE), + ).toThrow(/declares "tools:" twice in the same addition block/); + }); + + test("12: a line that is not a YAML key is a hard error", () => { + const src = ["---", "name: dev", "---", "body", ""].join("\n"); + expect(() => applyFrontmatterAdditions(src, ["not a key at all"], FILE)).toThrow( + /does not start with a YAML key/, + ); + }); + + test("13: a file with no frontmatter block is a hard error", () => { + expect(() => applyFrontmatterAdditions("# just prose\n", ["tools: []"], FILE)).toThrow( + /no leading frontmatter block/, + ); + }); +}); + +describe("t249 the two seams compose (the shipped kiro-ide order)", () => { + test("14: removals then additions yields one valid block with no duplicates", () => { + // The packager applies removals BEFORE additions, which is what lets the IDE + // manifest drop the CLI-only `disallowedTools` and add its own `tools:` + + // `permissions:` without a collision. + const src = [ + "---", + "name: aidlc-developer-agent", + "description: Implements units of work", + "disallowedTools:", + " - Task", + "", + " - Other", + "tier: judgment", + "---", + "# Developer", + "", + ].join("\n"); + const trimmed = applyFrontmatterRemovals(src, ["disallowedTools"], FILE); + const out = applyFrontmatterAdditions( + trimmed, + ['tools: ["read", "write", "shell"]', "permissions:", " rules:", " - capability: shell"], + FILE, + ); + const keys = topLevelKeys(fmOf(out)); + expect(keys).toEqual(["name", "description", "tier", "tools", "permissions"]); + expect(new Set(keys).size).toBe(keys.length); // no duplicate top-level key + expect(hasOrphanContinuation(fmOf(out))).toBe(false); + expect(out).not.toContain("disallowedTools"); + expect(out).not.toContain("Other"); + expect(out).toContain("# Developer"); + }); +});