Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
{
"name": "aidd-dev",
"source": "./plugins/aidd-dev",
"description": "Code transformation: plan, implement, assert, audit, review, test, refactor, debug, for-sure. Hosts engineering agents.",
"description": "Code transformation: plan, implement, assert, audit, review, test, refactor, debug, for-sure.",
"strict": true,
"metadata": {
"recommended": true
Expand All @@ -46,7 +46,7 @@
{
"name": "aidd-orchestrator",
"source": "./plugins/aidd-orchestrator",
"description": "Orchestration: synchronous SDLC pipeline, async issue-to-PR automation, and product backlog.",
"description": "Orchestration: synchronous SDLC pipeline, async issue-to-PR automation, and product backlog. Hosts the generic agents.",
"strict": true,
"metadata": {
"recommended": true
Expand Down
20 changes: 16 additions & 4 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
## Behavior

- **Stay critical.** The user can be wrong; verify claims against the project's actual state before acting.
- **Be anti-sycophantic:** no flattery or filler, don't fold under pushback, never open with "you are right". Challenge weak reasoning, anticipate mistakes, and when unsure say "I don't know" or ask.
- **Be anti-sycophantic:** no flattery or filler; agree only when the evidence supports it, and don't fold under pushback. Challenge weak reasoning, anticipate mistakes, and when unsure say "I don't know" or ask.
- **Surface tradeoffs and evaluate their impact** instead of hiding them.

## Communication
Expand All @@ -14,7 +14,7 @@
- **No preamble or recap:** don't restate the request or summarize visible changes. Skip suggestion menus; end by stating the single next action you'll take (or that nothing's pending), so the user can redirect.
- **Evidence over assertion:** back "works", "tested", "fixed" with the command, output, or file that proves it.
- **Quote the shortest decisive line** of an error or log, not the whole dump.
- **No tool-call narration.** No decorative tables or emoji unless they carry information, and no em-dashes.
- **Progress at milestones, not per call:** before a multi-step tool run, one line on what you're doing and why; no commentary on individual calls. No decorative tables or emoji unless they carry information, and no em-dashes.
- **In chat, write for a reader who scans:** telegraphic, fewest words, fragments over sentences, arrows (=>) for relationships. Cut any word that doesn't change meaning. Normal prose in authored docs and code. Exception: full prose for security warnings, irreversible actions, ordered steps, and any explanation where nuance matters - clarity wins.

## Action
Expand All @@ -23,14 +23,26 @@
- **Stay focused, not scattered:** exceed the literal ask only when it clearly helps, not by default. When you spot an unrelated issue, note it in one line and keep going; detour only if it blocks the task.
- **Solve your own issues first:** genuinely try to resolve it yourself before escalating to the human.
- **Don't assume your knowledge is current.**
- **Placement discipline:** for every plugin change, think hard about where responsibility belongs; follow `docs/ARCHITECTURE.md`.
- **Placement discipline:** for every plugin change, place the responsibility in the plugin whose concern owns it, per `docs/ARCHITECTURE.md`.
- **Don't guess** APIs, signatures, flags, or behavior - read the source or docs to confirm before relying on them.
- **Ambiguous or expensive task:** ask one sharp question to pin down scope before building, rather than guess.
- **Batch independent operations** in one pass, not one at a time.
- **Fan out** independent subtasks to parallel subagents when you own the overall flow and the work is genuinely parallel.
- **Before adding any instruction, finding, or rule, check whether an existing one already covers or contradicts it.** If so, don't add a parallel: delete it, merge it into the stronger one, or rewrite with explicit scope and priority.
- **Name by intention, not mechanism:** describe the goal or responsibility, not the tool or file format.

## Agents

When you own the overall flow, fan out genuinely independent subtasks to agents by responsibility when coordination costs less than serial work. You stay the caller: you own scope, delegation, and final acceptance.

| Responsibility | Agent |
| --- | --- |
| Answer a scoped codebase question with sources | `explorer` |
| Implement assigned work and verify it | `executor` |
| Confirm the outcome meets its acceptance criteria | `validator` |
| Review quality, coherence, and needless complexity | `reviewer` |

Without the agent, give the same brief to the host's default subagent.

## Memory Management

Project docs, memory, specs, and plans live in `aidd_docs/`.
Expand Down
14 changes: 13 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,22 @@
- **Don't guess** APIs, signatures, flags, or behavior - read the source or docs to confirm before relying on them.
- **Ambiguous or expensive task:** ask one sharp question to pin down scope before building, rather than guess.
- **Batch independent operations** in one pass, not one at a time.
- **Fan out** independent subtasks to parallel subagents when you own the overall flow and the work is genuinely parallel.
- **Before adding any instruction, finding, or rule, check whether an existing one already covers or contradicts it.** If so, don't add a parallel: delete it, merge it into the stronger one, or rewrite with explicit scope and priority.
- **Name by intention, not mechanism:** describe the goal or responsibility, not the tool or file format.

## Agents

When you own the overall flow, fan out genuinely independent subtasks to agents by responsibility when coordination costs less than serial work. You stay the caller: you own scope, delegation, and final acceptance.

| Responsibility | Agent |
| --- | --- |
| Answer a scoped codebase question with sources | `explorer` |
| Implement assigned work and verify it | `executor` |
| Confirm the outcome meets its acceptance criteria | `validator` |
| Review quality, coherence, and needless complexity | `reviewer` |

Without the agent, give the same brief to the host's default subagent.

## Memory Management

Project docs, memory, specs, and plans live in `aidd_docs/`.
Expand Down
7 changes: 3 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
PLUGIN ?= all

.DEFAULT_GOAL := help
.PHONY: help setup doctor check reload

Expand All @@ -17,5 +15,6 @@ doctor: ## Check the local toolchain
check: ## Run the pre-commit checks
pnpm exec lefthook run pre-commit

reload: ## Dev: reload this checkout into Claude, Codex, and OpenCode (PLUGIN="aidd-refine aidd-pm", default all)
scripts/dev-sync.sh $(PLUGIN)
reload: ## Dev: reload all plugins into Claude, Codex, OpenCode, Copilot, and Cursor
pnpm --dir cli build
scripts/dev-sync.sh
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Unify **engineering teams** around **standardized workflows** and **shared best
🧱 **IDE agnostic** · 🏗️ **Legacy systems** · 🌱 **Token-optimized** · 🇫🇷 **Made in France**

<p>
<!--counts:start--><kbd>9 plugins</kbd> · <kbd>52 skills</kbd> · <kbd>2 agents</kbd><!--counts:end-->
<!--counts:start--><kbd>9 plugins</kbd> · <kbd>52 skills</kbd> · <kbd>4 agents</kbd><!--counts:end-->
</p>

[![Open Source](https://img.shields.io/badge/Open_Source-Yes-yellow?logo=open-source-initiative&logoColor=white)](https://opensource.org/)
Expand Down
1 change: 0 additions & 1 deletion aidd_docs/memory/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ The `aidd` binary, built from `cli/` and published to npm as `@ai-driven-dev/cli

## Commands

- Eleven groups: `setup`, `framework`, `translate`, `plugin`, `marketplace`, `auth`, `sync`, `update`, `doctor`, `clean`, `telemetry`.
- `telemetry` counts the tokens of Claude Code and Codex sessions locally: [usage contract](../product/usage-contract.md).
- No list here. The surface moves; `aidd --help` is the only reading that stays true.

Expand Down
6 changes: 5 additions & 1 deletion aidd_docs/memory/deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ Branch model in `vcs.md`, cadence and safety rules in [`RELEASE.md`](../../RELEA
flowchart TD
RP["release-please PR, auto-merged"] --> Tags["tags + umbrella release as draft"]
Tags --> Back["back-merge.yml: main into next"]
Tags --> Jobs["attach: bundle, 9 distributions, plugin archives, video"]
Tags --> Jobs["attach: bundle, per-tool distributions, plugin archives, video"]
Tags --> Cli["publish-cli: npm"]
Jobs --> Pub["publish-release: draft to latest"]
Cli --> Recap
Expand All @@ -63,6 +63,10 @@ Config: `release-please-config.json`, eleven packages. Manifest: `.release-pleas

- `build-per-tool` builds the CLI from this run's own checkout (`pnpm build`, then `node cli/dist/cli.js translate`), never a pinned published version: nothing to bump, nothing to go stale.

## Local reload

`make reload` syncs all plugins and generic delegation guidance to installed hosts; details in `scripts/dev-sync.sh`.

## Monitoring

None. Failures are a red run; `back-merge.yml` opens an issue when it cannot push.
44 changes: 44 additions & 0 deletions aidd_docs/tasks/2026_10/2026_10_14_sub_agents/review.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Review: scoped sub-agents

- Rounds: 3
- Started: 2026-10-15

## Round 1 · r-1fd6

- Date: 2026-10-15
- By: alexsoyes
- Diff: `origin/next...513d323c0dcb431aa936e56bf4be16945e39ec57`
- Axes: code, relevancy
- Verdict: changes-requested
- Score: not scored

### Findings

- `plugins/aidd-orchestrator/skills/01-sdlc/references/02-deliver.md:49` : Delegated delivery sends the required final journey into Finalize, whose first step runs plan validation again (`02-implement/actions/03-finalize.md:13`). The journey is therefore no longer last → perform integrated validation before that journey and mark completion after it passes — 🟡 major, fit
- `plugins/aidd-context/skills/06-agent-generate/references/agent-authoring.md:25` : The changed contract requires canonical recipe addresses, while the copied scaffold still prescribes capability discovery for cross-plugin recipes (`assets/agent-template.md:18`; `actions/02-write-agent.md:15` copies it) → align the scaffold with the contract — 🟡 major, architecture
- `plugins/aidd-dev/skills/02-implement/actions/02-execute.md:17` : Missing dependencies demand replanning, while line 15 gives undeclared dependencies a serial fallback → distinguish absent declarations from unresolved referenced prerequisites — 🟢 minor, error-handling
- `docs/ARCHITECTURE.md:145` : Rewriting general cross-plugin provider discovery is unnecessary for adding sub-agents; agent permission addressing already has its own row → retain the existing provider rule — 🟢 minor, fit

## Round 2 · r-7c2a

- Date: 2026-10-15
- By: alexsoyes
- Diff: `origin/next...513d323c0dcb431aa936e56bf4be16945e39ec57` plus the working tree
- Axes: code, relevancy
- Verdict: changes-requested
- Score: not scored

### Findings

- `plugins/aidd-orchestrator/skills/01-sdlc/references/02-deliver.md:7` : The local correction makes every executor stop after Execute, including whole-plan executors, while the implementation router still instructs whole-plan calls to run Prepare, Execute and Finalize (`02-implement/SKILL.md:26`). The caller must override that routing and resume inside another action → preserve the normal whole-plan route and keep shared integration/finalization ownership specific to delegated phases — 🟡 major, architecture
- `plugins/aidd-dev/skills/02-implement/actions/02-execute.md:16` : Distinct checkouts/Git indexes are mandatory for parallel execution even when workers own disjoint files and leave Git operations to the caller → require independent writes and validation resources; require separate indexes only when workers also perform Git operations — 🟢 minor, fit
- `plugins/aidd-dev/agents/validator.md:19` : A two-sentence maximum can hide distinct failures or verification blockers; the requested concise verdict does not need a fixed sentence count → retain one verdict and concise decisive evidence without the numeric cap — 🟢 minor, fit

## Round 3 · r-983d

- Date: 2026-10-15
- By: alexsoyes
- Diff: final working candidate
- Axes: code, relevancy
- Verdict: approve
- Score: not scored
17 changes: 17 additions & 0 deletions aidd_docs/tasks/2026_10/2026_10_14_sub_agents/verification.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Sub-agent verification

Behavior and sources are in [the agent guide](../../../../docs/SUBAGENTS.md).

## Scope

- **Agents:** explorer, executor, validator and reviewer ship in `plugins/aidd-orchestrator/agents/`, installed with the plugin. No tool list is declared: every host gives an agent all tools by default.
- **Translation:** each host receives only the keys its documentation lists: name or file path as the ID, description, model, and Claude's `effort` under the host's own key. Each host has one agent frontmatter function, shared by the plugin install and its built distributions.
- **Out of scope:** per-provider models and a model for the main session.

## Checks

- **Claude Code:** the four agents load and run from a project-scoped plugin install.
- **OpenCode:** the four agents run from the flat distribution through `opencode run --standalone --agent <id>` with an OpenAI model, each answering after a `read` call.
- **Codex:** the four agents load from the flat distribution in a trusted project; `codex exec` spawned each, and its session records the agent's role and instructions.
- **Every host:** `cli/tests/e2e/agent-install.e2e.test.ts` builds the repository flat and checks each shipped agent's path, frontmatter and body against the host's documented format.
- **Copilot, Cursor, Kilo:** no host binary in the test environment, so loading by the host is unverified. The Copilot plugin lists agent files where its documentation describes agent directories.
42 changes: 10 additions & 32 deletions cli/src/contexts/tools/domain/capabilities/agents-capability.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { parseFrontmatter, serializeFrontmatter } from "../../../../kernel/markdown.js";
import type { AgentFrontmatter } from "../formats/agent-format.js";

function agentNameFromFrontmatter(
fm: Record<string, unknown>,
Expand All @@ -9,22 +10,6 @@ function agentNameFromFrontmatter(
return typeof name === "string" ? name : undefined;
}

function tomlString(value: string): string {
return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
}

function buildTomlContent(frontmatter: Record<string, unknown>, body: string): string {
const lines: string[] = [
`name = ${tomlString(String(frontmatter.name ?? ""))}`,
`description = ${tomlString(String(frontmatter.description ?? ""))}`,
];
if (frontmatter.model !== undefined) {
lines.push(`model = ${tomlString(String(frontmatter.model))}`);
}
lines.push(`developer_instructions = """\n${body}\n"""`);
return `${lines.join("\n")}\n`;
}

function stripSuffix(toolSuffix: string, fileName: string): string {
const basename = fileName.split("/").at(-1) ?? fileName;
const dir = fileName.slice(0, fileName.length - basename.length);
Expand All @@ -51,12 +36,14 @@ export class AgentsCapability {
directory: string;
toolSuffix: string;
format: "markdown" | "toml";
/** The host's own agent frontmatter, shared with its built distributions. */
frontmatter: AgentFrontmatter;
userFileExt?: string;
/** How frontmatter strings are quoted; `double` for readers that keep single quotes. */
quote?: "single" | "double";
/** Writes the agent file when the host's format is not markdown frontmatter. */
serialize?: (frontmatter: Record<string, unknown>, body: string) => string;
buildInstallPath?: (fileName: string) => string | null;
convertFrontmatter?: (
fm: Record<string, unknown>,
fileName?: string
) => Record<string, unknown>;
}
) {}

Expand Down Expand Up @@ -84,21 +71,12 @@ export class AgentsCapability {
}

convertFrontmatter(fm: Record<string, unknown>, fileName?: string): Record<string, unknown> {
if (this.params.convertFrontmatter) return this.params.convertFrontmatter(fm, fileName);
const name = agentNameFromFrontmatter(fm, fileName);
if (this.params.format === "toml") {
const result: Record<string, unknown> = { name, description: fm.description };
if (fm.model !== undefined) result.model = fm.model;
return result;
}
return { name, description: fm.description };
return this.params.frontmatter({ ...fm, name: agentNameFromFrontmatter(fm, fileName) });
}

serialize(frontmatter: Record<string, unknown>, body: string): string {
if (this.params.format === "toml") {
return buildTomlContent(frontmatter, body);
}
return serializeFrontmatter(frontmatter, body);
if (this.params.serialize) return this.params.serialize(frontmatter, body);
return serializeFrontmatter(frontmatter, body, this.params.quote);
}

deserialize(content: string): { frontmatter: Record<string, unknown>; body: string } {
Expand Down
23 changes: 23 additions & 0 deletions cli/src/contexts/tools/domain/formats/agent-format.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/** One host's agent frontmatter, written from the Claude-format source. Every host declares
* exactly one, and every path that installs an agent writes through it, so the plugin
* install and the built distributions cannot diverge. */
export type AgentFrontmatter = (source: Record<string, unknown>) => Record<string, unknown>;

/** Pick only the given keys, in their order, for deterministic output. A key whose value is
* undefined is omitted. */
export function pickFrontmatterKeys(
fm: Record<string, unknown>,
keys: readonly string[]
): Record<string, unknown> {
const result: Record<string, unknown> = {};
for (const key of keys) {
if (fm[key] !== undefined) result[key] = fm[key];
}
return result;
}

/** A host without an effort key reads it from the model id, between `open` and `close`. */
export function modelWithEffort(fm: Record<string, unknown>, open: string, close = ""): unknown {
if (typeof fm.model !== "string" || typeof fm.effort !== "string") return fm.model;
return `${fm.model}${open}${fm.effort}${close}`;
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@ export const COPILOT_AGENT_FRONTMATTER_KEYS: readonly [
"name",
"description",
"model",
"tools",
"agents",
"argument-hint",
] = ["name", "description", "model", "tools", "agents", "argument-hint"];
"reasoningEffort",
"include-custom-instructions",
] = ["name", "description", "model", "reasoningEffort", "include-custom-instructions"];

/** Cursor-supported frontmatter keys: Cursor documents only name, description and model —
* never tools or color. */
Expand All @@ -17,6 +16,9 @@ export const CURSOR_AGENT_FRONTMATTER_KEYS: readonly ["name", "description", "mo
"model",
];

/** Keys of a host whose agent ID is its file path (OpenCode, Kilo): no `name`. */
const PATH_ID_AGENT_FRONTMATTER_KEYS: readonly ["description", "model"] = ["description", "model"];

/** Pick only the given keys, preserving their order. A key whose value is undefined is
* omitted. */
export function pickFrontmatterKeys(
Expand All @@ -32,17 +34,26 @@ export function pickFrontmatterKeys(
return result;
}

/** Only the Copilot-supported keys, in the allowlist's own order. Lossy, so there is no
* inverse: a key outside the allowlist cannot be recovered from the output. */
/** Copilot reads Claude's `effort` as `reasoningEffort`, and gives a subagent the repository
* instructions only when `include-custom-instructions` is set. Lossy, so there is no inverse. */
export function stripCopilotAgentFrontmatter(fm: Record<string, unknown>): Record<string, unknown> {
return pickFrontmatterKeys(fm, COPILOT_AGENT_FRONTMATTER_KEYS);
return pickFrontmatterKeys(
{
...fm,
reasoningEffort: fm.effort,
"include-custom-instructions": fm["include-custom-instructions"] ?? true,
},
COPILOT_AGENT_FRONTMATTER_KEYS
);
}

/** Only the Cursor-supported keys. Tools, color and argument-hint are discarded. */
export function stripCursorAgentFrontmatter(fm: Record<string, unknown>): Record<string, unknown> {
return pickFrontmatterKeys(fm, CURSOR_AGENT_FRONTMATTER_KEYS);
}

export function stripAgentFrontmatter(fm: Record<string, unknown>): Record<string, unknown> {
return stripCopilotAgentFrontmatter(fm);
/** OpenCode and Kilo name an agent after its file and give it every tool by default; Kilo
* passes any unknown key to the model provider, so nothing else is carried. */
export function stripPathIdAgentFrontmatter(fm: Record<string, unknown>): Record<string, unknown> {
return pickFrontmatterKeys(fm, PATH_ID_AGENT_FRONTMATTER_KEYS);
}
Loading
Loading