From bd2100866a5d8bac3f663793797388199c46e39d Mon Sep 17 00:00:00 2001 From: alexsoyes Date: Wed, 14 Oct 2026 12:28:15 +0800 Subject: [PATCH 01/73] feat(aidd-dev): record phase dependencies in plans Expose prerequisites before introducing parallel execution and preserve ordering when independence is uncertain. Refs #983 --- .../skills/01-plan/actions/04-plan.md | 30 +++++++++++++------ .../skills/01-plan/assets/plan-template.md | 10 ++++--- 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/plugins/aidd-dev/skills/01-plan/actions/04-plan.md b/plugins/aidd-dev/skills/01-plan/actions/04-plan.md index 0803da0ff..b431aae05 100644 --- a/plugins/aidd-dev/skills/01-plan/actions/04-plan.md +++ b/plugins/aidd-dev/skills/01-plan/actions/04-plan.md @@ -13,6 +13,10 @@ A feature folder, always at `aidd_docs/tasks//_/_/_/plan.md` exists with one `phase-.md` per phase next to it. -- Every written file satisfies its template's inline contract. -- No `{...}` placeholder is left in any written file. -- The phase projection slices together cover the modify, create, and delete lists. -- A confidence score was reported and written to no file. -- An autonomous run waits only for a product decision that the source cannot resolve. -- A newly created folder whose source names a ticket carries a `backlog-link.json` naming it; reusing an existing folder never overwrites one already there. +| Case | Pass | +| --- | --- | +| The plan is written | The feature folder holds `plan.md` and one `phase-.md` per phase. | +| Written files are read back | Each satisfies its template's inline contract with no `{...}` placeholder left. | +| Phase projections are combined | They cover the modify, create, and delete lists. | +| Dependencies are reviewed | Every prerequisite names an existing earlier phase; no phase depends on itself. | +| Phases share a required output, conflicting file changes, or mutable validation resources | Their ordering is recorded in the phase table. | +| Phase independence is uncertain | The plan preserves ordering. | +| The plan is scored | A confidence score was reported and written to no file. | +| The run is autonomous | It waits only for a product decision that the source cannot resolve. | +| A new folder's source names a ticket | `backlog-link.json` names it; reusing a folder never overwrites an existing link. | diff --git a/plugins/aidd-dev/skills/01-plan/assets/plan-template.md b/plugins/aidd-dev/skills/01-plan/assets/plan-template.md index 79301f70f..4321609d5 100644 --- a/plugins/aidd-dev/skills/01-plan/assets/plan-template.md +++ b/plugins/aidd-dev/skills/01-plan/assets/plan-template.md @@ -16,10 +16,12 @@ status: pending ## Phases -| # | Phase | File | -| --- | ------------ | ---------------------------- | -| 1 | {phase-name} | [`phase-1.md`](./phase-1.md) | -| 2 | {phase-name} | [`phase-2.md`](./phase-2.md) | + + +| # | Phase | File | Depends on | +| --- | ------------ | ---------------------------- | ---------- | +| 1 | {phase-name} | [`phase-1.md`](./phase-1.md) | {none} | +| 2 | {phase-name} | [`phase-2.md`](./phase-2.md) | {phase numbers or none} | ## Resources From 009e5ed1bdde9bf82b8cc677ef6976ab0f6abc9e Mon Sep 17 00:00:00 2001 From: alexsoyes Date: Wed, 14 Oct 2026 12:29:28 +0800 Subject: [PATCH 02/73] fix(framework): reload nested opencode skills Handle current nested output and legacy flat output without reporting success when selected skills are missing. Preserve unrelated plugins during refresh. Refs #983 --- scripts/__tests__/dev-sync.test.js | 80 ++++++++++++++++++++++-------- scripts/dev-sync.sh | 17 +++++-- 2 files changed, 74 insertions(+), 23 deletions(-) diff --git a/scripts/__tests__/dev-sync.test.js b/scripts/__tests__/dev-sync.test.js index 01a42e0ea..9c37bbf01 100644 --- a/scripts/__tests__/dev-sync.test.js +++ b/scripts/__tests__/dev-sync.test.js @@ -30,6 +30,7 @@ function runSync(fakeBin, home, args = ["all"]) { PATH: [fakeBin, BASE_PATH].join(delimiter), HOME: home, BUILD: join(home, "build"), + OPENCODE_SKILLS: join(home, ".config/opencode/skills"), }, encoding: "utf8", }); @@ -53,33 +54,72 @@ test("managed OpenCode reload uses the fixed-purpose helper without a local buil } }); -test("local OpenCode reload installs only the selected plugin skills globally", () => { - const root = mkdtempSync(join(tmpdir(), "aidd-dev-sync-local-")); +for (const layout of ["flat", "nested"]) { + test(`local OpenCode reload refreshes only the selected plugin using ${layout} output`, () => { + const root = mkdtempSync(join(tmpdir(), "aidd-dev-sync-local-")); + try { + const fakeBin = join(root, "bin"); + const home = join(root, "home"); + mkdirSync(fakeBin); + mkdirSync(home); + mkdirSync(join(home, ".config/opencode/skills/aidd-dev-stale"), { recursive: true }); + writeFileSync(join(home, ".config/opencode/skills/aidd-dev-stale/SKILL.md"), "stale\n"); + mkdirSync(join(home, ".config/opencode/skills/aidd-dev/removed"), { recursive: true }); + writeFileSync(join(home, ".config/opencode/skills/aidd-dev/removed/SKILL.md"), "stale\n"); + mkdirSync(join(home, ".config/opencode/skills/aidd-dev/01-plan"), { recursive: true }); + writeFileSync(join(home, ".config/opencode/skills/aidd-dev/01-plan/SKILL.md"), "old\n"); + const unrelated = join(home, ".config/opencode/skills/aidd-pm/03-prd/SKILL.md"); + mkdirSync(join(home, ".config/opencode/skills/aidd-pm/03-prd"), { recursive: true }); + writeFileSync(unrelated, "keep\n"); + executable(join(fakeBin, "opencode"), "exit 0"); + const skillName = layout === "nested" ? "aidd-dev/01-plan" : "aidd-dev-01-plan"; + executable( + join(fakeBin, "npx"), + String.raw`out="" +while [ "$#" -gt 0 ]; do + if [ "$1" = "--out" ]; then shift; out=$1; fi + shift +done +skill="$out/.opencode/skills/${skillName}" +mkdir -p "$skill/actions" "$skill/assets" +printf '%s\n' '---' 'name: aidd-dev-01-plan' 'description: test' '---' > "$skill/SKILL.md" +printf '%s\n' 'updated action' > "$skill/actions/04-plan.md" +printf '%s\n' 'updated template' > "$skill/assets/plan-template.md"`, + ); + + const result = runSync(fakeBin, home, ["aidd-dev"]); + assert.equal(result.status, 0, result.stderr); + const installed = join(home, ".config/opencode/skills", skillName); + assert.match(readFileSync(join(installed, "SKILL.md"), "utf8"), /name: aidd-dev-01-plan/); + assert.equal(readFileSync(join(installed, "actions/04-plan.md"), "utf8"), "updated action\n"); + assert.equal(readFileSync(join(installed, "assets/plan-template.md"), "utf8"), "updated template\n"); + assert.equal(existsSync(join(home, ".config/opencode/skills/aidd-dev-stale")), false); + assert.equal(existsSync(join(home, ".config/opencode/skills/aidd-dev/removed")), false); + assert.equal(readFileSync(unrelated, "utf8"), "keep\n"); + assert.match(result.stdout, /install opencode\s+skills:ok/); + } finally { + rmSync(root, { recursive: true, force: true }); + } + }); +} + +test("local OpenCode reload rejects missing selected skills before removing installed ones", () => { + const root = mkdtempSync(join(tmpdir(), "aidd-dev-sync-missing-")); try { const fakeBin = join(root, "bin"); const home = join(root, "home"); mkdirSync(fakeBin); - mkdirSync(home); - mkdirSync(join(home, ".config/opencode/skills/aidd-dev-stale"), { recursive: true }); - writeFileSync(join(home, ".config/opencode/skills/aidd-dev-stale/SKILL.md"), "stale\n"); + const installed = join(home, ".config/opencode/skills/aidd-dev-01-plan/SKILL.md"); + mkdirSync(join(home, ".config/opencode/skills/aidd-dev-01-plan"), { recursive: true }); + writeFileSync(installed, "keep\n"); executable(join(fakeBin, "opencode"), "exit 0"); - executable( - join(fakeBin, "npx"), - String.raw`out="" -while [ "$#" -gt 0 ]; do - if [ "$1" = "--out" ]; then shift; out=$1; fi - shift -done -mkdir -p "$out/.opencode/skills/aidd-dev-01-plan" -printf '%s\n' '---' 'name: aidd-dev-01-plan' 'description: test' '---' > "$out/.opencode/skills/aidd-dev-01-plan/SKILL.md"`, - ); + executable(join(fakeBin, "npx"), "exit 0"); const result = runSync(fakeBin, home, ["aidd-dev"]); - assert.equal(result.status, 0, result.stderr); - const installed = join(home, ".config/opencode/skills/aidd-dev-01-plan/SKILL.md"); - assert.match(readFileSync(installed, "utf8"), /name: aidd-dev-01-plan/); - assert.equal(existsSync(join(home, ".config/opencode/skills/aidd-dev-stale")), false); - assert.match(result.stdout, /install opencode\s+skills:ok/); + assert.notEqual(result.status, 0); + assert.match(result.stderr, /no built OpenCode skills for aidd-dev/); + assert.doesNotMatch(result.stdout, /skills:ok/); + assert.equal(readFileSync(installed, "utf8"), "keep\n"); } finally { rmSync(root, { recursive: true, force: true }); } diff --git a/scripts/dev-sync.sh b/scripts/dev-sync.sh index 29cb7d18c..750feb4f8 100755 --- a/scripts/dev-sync.sh +++ b/scripts/dev-sync.sh @@ -38,12 +38,23 @@ build_tool() { sync_opencode_skills() { local name source skill destination + local -a skills mkdir -p "$OPENCODE_SKILLS" + source="$BUILD/opencode/.opencode/skills" for name in "$@"; do - source="$BUILD/opencode/.opencode/skills" + skills=("$source/$name/"*/ "$source/$name-"*/) + if [ "${#skills[@]}" -eq 0 ]; then + echo "no built OpenCode skills for $name" >&2 + return 1 + fi + rm -rf -- "$OPENCODE_SKILLS/$name" find "$OPENCODE_SKILLS" -mindepth 1 -maxdepth 1 -type d -name "$name-*" -exec rm -rf -- {} + - for skill in "$source/$name-"*/; do - destination="$OPENCODE_SKILLS/$(basename "$skill")" + for skill in "${skills[@]}"; do + case "$skill" in + "$source/$name/"*) destination="$OPENCODE_SKILLS/$name/$(basename "$skill")" ;; + *) destination="$OPENCODE_SKILLS/$(basename "$skill")" ;; + esac + mkdir -p "$(dirname "$destination")" cp -R "$skill" "$destination" done done From 1f151d191012d93b1ba43a7a0d073ff571c8e20a Mon Sep 17 00:00:00 2001 From: alexsoyes Date: Wed, 14 Oct 2026 13:27:02 +0800 Subject: [PATCH 03/73] feat(aidd-dev): add scoped sub-agent workflows Separate exploration, implementation, completion validation and quality review. Allow assigned phases and independent batches while keeping shared state and acceptance with the caller. Refs #983 --- AGENTS.md | 13 ++++++ README.md | 2 +- docs/ARCHITECTURE.md | 10 ++--- .../02-project-memory/actions/04-sync.md | 12 +++++- .../assets/templates/AGENTS.md | 9 ++++ plugins/aidd-dev/.claude-plugin/plugin.json | 2 + plugins/aidd-dev/CATALOG.md | 6 ++- plugins/aidd-dev/agents/checker.md | 15 ++++--- plugins/aidd-dev/agents/executor.md | 6 +-- plugins/aidd-dev/agents/explorer.md | 24 +++++++++++ plugins/aidd-dev/agents/validator.md | 30 ++++++++++++++ plugins/aidd-dev/skills/01-plan/SKILL.md | 36 +++++++++------- .../skills/01-plan/actions/02-explore.md | 13 ++++-- .../skills/01-plan/references/plan-status.md | 2 +- plugins/aidd-dev/skills/02-implement/SKILL.md | 41 +++++++++++++------ .../skills/02-implement/actions/01-prepare.md | 11 ++--- .../skills/02-implement/actions/02-execute.md | 39 ++++++++++++------ .../02-implement/actions/03-finalize.md | 15 +++++-- .../skills/02-implement/references/blocked.md | 2 +- .../aidd-orchestrator/skills/01-sdlc/SKILL.md | 4 +- .../skills/01-sdlc/references/02-deliver.md | 19 ++++++--- .../skills/01-sdlc/references/03-check.md | 17 +++++--- 22 files changed, 238 insertions(+), 90 deletions(-) create mode 100644 plugins/aidd-dev/agents/explorer.md create mode 100644 plugins/aidd-dev/agents/validator.md diff --git a/AGENTS.md b/AGENTS.md index 53ad41f8b..94caba638 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -32,6 +32,19 @@ - **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 + +Use available agents when useful. The caller owns scope, delegation, and final acceptance; no mandatory sequence. + + +| name | role | +| --- | --- | +| @explorer (Codex), @aidd-dev-explorer (OpenCode) | Explore scoped questions. Return sourced findings, uncertainties, and risks. Never modify inspected material. | +| @executor (Codex), @aidd-dev-executor (OpenCode) | Implement assigned scope. Validate, repair failures, and report evidence and blockers. Never change requirements. | +| @validator (Codex), @aidd-dev-validator (OpenCode) | Validate supplied criteria and mandatory checks. Report PASS, FAIL, or BLOCKED with evidence. Never repair. | +| @checker (Codex), @aidd-dev-checker (OpenCode) | Review quality, risks, and fitness for the need. Report actionable findings. Never modify the deliverable. | + + ## Memory Management Project docs, memory, specs, and plans live in `aidd_docs/`. diff --git a/README.md b/README.md index 760238e8d..d49c184a9 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ Unify **engineering teams** around **standardized workflows** and **shared best 🧱 **IDE agnostic** · 🏗️ **Legacy systems** · 🌱 **Token-optimized** · 🇫🇷 **Made in France**

- 9 plugins · 51 skills · 2 agents + 9 plugins · 51 skills · 4 agents

[![Open Source](https://img.shields.io/badge/Open_Source-Yes-yellow?logo=open-source-initiative&logoColor=white)](https://opensource.org/) diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 486617d92..9db584b29 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -147,16 +147,16 @@ A skill never links outside itself (`scripts/__tests__/a-skill-links-only-inside Choose by context, not complexity: keep the work visible to the caller → skill; isolate it and take only the result → agent. -- **Spawning is authorized by the high-level orchestrator, never invented by a recipe skill.** A recipe skill normally runs in the caller's context. A bounded fan-out capability may mechanically spawn leaf agents only when the orchestrator explicitly delegates that responsibility and retains routing ownership. -- An orchestrator spawns each isolated step as a leaf agent that runs a recipe, or runs the recipe itself when isolation is unnecessary. The SDLC owns planning, delegates delivery to `executor`, and delegates independent judgments to a fresh `checker`. For independent repair findings, it may explicitly delegate bounded fan-out to `10-todo`; Todo's leaf executors return their results to the SDLC. A recipe invoked inside an agent never spawns again. -- An agent invokes only the recipe skills it declares under `# Skills you may invoke`, never an orchestrator skill, and never reads a skill's files. It names every skill by its canonical `/plugin:folder` address so its permissions are explicit and auditable. -- An agent never delegates flow work to another agent and never invokes an orchestrator skill. It may spawn a read-only recon helper (for example `Explore`) that mutates nothing and spawns nothing. So the write path stays two layers deep and delegation can never cycle. +- **The primary caller owns delegation.** A user-invoked recipe may offer bounded delegation through available host capabilities. An orchestrator owns delegation when it invokes the recipe. Neither requires a fixed provider or model. +- A primary caller may delegate independent read-only questions to explorers and independent implementation phases to executors. It owns scope, dependencies, shared state, integration, and acceptance. Concurrent writers need distinct checkouts and nonconflicting validation resources; otherwise execution stays serial. +- An isolated agent is a leaf. It never spawns another agent or invokes an orchestrator. It invokes only recipe skills listed under `# Skills you may invoke`, using their canonical `/plugin:folder` addresses without reading their files. +- Independent validation uses a validator on an identified candidate. A checker reviews quality and outcome using that evidence. Neither modifies the candidate; gaps return to the primary caller for repair and renewed verification. ## 🔗 Capability addressing Address a capability only where the dispatch is declared: a router's `## Actions` table, an agent's `# Skills you may invoke` list. Everywhere else, name the concept the capability owns, never the skill that owns it. -Recipe skills never hardcode a sibling provider. They discover cross-plugin capabilities at runtime through description matching. Agent permission lists and orchestration references are responsibility maps, so they name the current provider with its canonical `/plugin:folder` or `@plugin:agent` address. The orchestrator must verify that provider is installed before calling it. +Recipe skills never hardcode a sibling provider. They discover cross-plugin capabilities at runtime through description matching. Agent permission lists name allowed skills with canonical `/plugin:folder` addresses. Orchestration references map responsibilities to providers discovered from installed descriptions; canonical addresses in diagrams illustrate current providers. Verify availability and the role contract before dispatch. Two paths are exempt, both in `isExemptFromOrthogonality`: diff --git a/plugins/aidd-context/skills/02-project-memory/actions/04-sync.md b/plugins/aidd-context/skills/02-project-memory/actions/04-sync.md index e96e752ae..9fa1dd693 100644 --- a/plugins/aidd-context/skills/02-project-memory/actions/04-sync.md +++ b/plugins/aidd-context/skills/02-project-memory/actions/04-sync.md @@ -8,7 +8,7 @@ The memory bank in `aidd_docs/memory/`. ## Output -Each picked tool's context file, carrying the filled block. +Each picked tool's context file, carrying the memory block and available agent table. ## Process @@ -20,7 +20,12 @@ Each picked tool's context file, carrying the filled block. - Its AIDD structure differs: offer to reconcile it, applying only what the user approves. 5. **Fill.** Run `hooks/update_memory.js` from the project root, naming the picked tools, and stop on a non-zero exit. - No script, the skill shipped alone: write each block from the bank. -6. **Verify.** Read each picked tool's block back and compare it to the bank. +6. **Agents.** Inspect the picked tools' available agent definitions and registration. Fill or replace only `aidd_agents:start` / `aidd_agents:end` with a `name | role` table. + - List only installed, invocable agents. Use their actual host identities, including plugin namespaces or flat prefixes; never assume a short role name is callable everywhere. + - Write short English descriptions beginning with the role's action verb. Keep detailed contracts in the agent definitions. + - When tools share a context file, label differing identities by host. Omit unavailable roles; leave only the table header if no agents are available. + - Preserve all user text outside the managed markers. Add the block when absent; do not add a discovery script or session hook. +7. **Verify.** Read each picked tool's block back and compare it to the bank. - A file in one and not the other: the fill did not land, report it and stop. ## Test @@ -32,3 +37,6 @@ Each picked tool's context file, carrying the filled block. | Picked tool | its block lists every root `.md` except `README.md`, nothing else | | Bank grew | the block gains that file and keeps the rest | | Unpicked tool | its context file is unchanged | +| Agent table | every row resolves to an installed agent on its labelled host | +| Agent unavailable | no row advertises it | +| Existing context | text outside managed blocks is preserved | diff --git a/plugins/aidd-context/skills/02-project-memory/assets/templates/AGENTS.md b/plugins/aidd-context/skills/02-project-memory/assets/templates/AGENTS.md index 84d30658d..bcefe20a0 100644 --- a/plugins/aidd-context/skills/02-project-memory/assets/templates/AGENTS.md +++ b/plugins/aidd-context/skills/02-project-memory/assets/templates/AGENTS.md @@ -31,6 +31,15 @@ - **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 + +Use available agents when useful. The caller owns scope, delegation, and final acceptance; no mandatory sequence. + + +| name | role | +| --- | --- | + + ## Memory Management Project docs, memory, specs, and plans live in `aidd_docs/`. diff --git a/plugins/aidd-dev/.claude-plugin/plugin.json b/plugins/aidd-dev/.claude-plugin/plugin.json index 766e5b871..bee38e7a9 100644 --- a/plugins/aidd-dev/.claude-plugin/plugin.json +++ b/plugins/aidd-dev/.claude-plugin/plugin.json @@ -20,7 +20,9 @@ "./skills/10-todo" ], "agents": [ + "./agents/explorer.md", "./agents/executor.md", + "./agents/validator.md", "./agents/checker.md" ], "keywords": [ diff --git a/plugins/aidd-dev/CATALOG.md b/plugins/aidd-dev/CATALOG.md index c54c4de54..32baab02c 100644 --- a/plugins/aidd-dev/CATALOG.md +++ b/plugins/aidd-dev/CATALOG.md @@ -32,8 +32,10 @@ Auto-generated index of skills, agents, references and assets shipped by the `ai | File | Description | |------|---| -| [checker.md](agents/checker.md) | `Judges finished work against its validator and the real need, leaving nothing unchecked. Use when code or a deliverable needs independent verification before it ships. Never edits the work, never implements the fix.` | +| [checker.md](agents/checker.md) | `Reviews quality, risks, and fitness for the intended need. Use for an independent judgment of a deliverable. Never edits the work or implements the fix.` | | [executor.md](agents/executor.md) | `Turns a dispatched task into working, validated code that fits the project. Use when an approved scope must become code. Never plans, never judges its own work.` | +| [explorer.md](agents/explorer.md) | `Explores scoped questions and returns sourced findings. Use when a caller needs evidence before deciding. Never modifies the inspected material.` | +| [validator.md](agents/validator.md) | `Validates an identified deliverable against supplied criteria and mandatory checks. Use for independent completion evidence. Never repairs or performs a general quality review.` | ### `skills` @@ -59,7 +61,7 @@ Auto-generated index of skills, agents, references and assets shipped by the `ai | `actions` | [02-execute.md](skills/02-implement/actions/02-execute.md) | - | | `actions` | [03-finalize.md](skills/02-implement/actions/03-finalize.md) | - | | `references` | [blocked.md](skills/02-implement/references/blocked.md) | `Conditions that make a plan blocked (needs a human).` | -| `-` | [SKILL.md](skills/02-implement/SKILL.md) | `Write an existing plan's code, phase by phase, until every acceptance criterion holds. Use when a plan exists and needs implementing. Do NOT use to write a plan, review a diff.` | +| `-` | [SKILL.md](skills/02-implement/SKILL.md) | `Implements an existing plan or an assigned phase until its acceptance criteria hold. Use when a plan or bounded phase needs implementing. Not for writing a plan or reviewing a diff.` | #### `skills/03-assert` diff --git a/plugins/aidd-dev/agents/checker.md b/plugins/aidd-dev/agents/checker.md index 6f0752098..62aea7815 100644 --- a/plugins/aidd-dev/agents/checker.md +++ b/plugins/aidd-dev/agents/checker.md @@ -1,20 +1,19 @@ --- name: checker -description: Judges finished work against its validator and the real need, leaving nothing unchecked. Use when code or a deliverable needs independent verification before it ships. Never edits the work, never implements the fix. -model: opus +description: Reviews quality, risks, and fitness for the intended need. Use for an independent judgment of a deliverable. Never edits the work or implements the fix. --- # Role -You are the checker. Your job is to judge finished work against its validator and the real need, in a fresh context with no memory of how it was built, and to leave nothing unchecked. +Review the deliverable's quality, risks, and fitness for its intended need in a fresh context. # Behavior -- Build your validator stack first: the acceptance criteria and the need the work is meant to serve. Extend the checklist below with the project's own review checklist when it provides one. -- Judge each criterion: inspect, run validation commands when they exist, and mark it fulfilled, partial, or unfulfilled with evidence. +- Read the intended need, acceptance criteria, candidate identity, and available validation evidence. Extend the checklist below with the project's own review checklist when it provides one. +- Use existing completion evidence. Repeat targeted checks only when it is insufficient, inconsistent, or stale; report missing validation instead of duplicating the full completion suite. - Run the checklist on every code or diff, leaving no item unchecked. - Then check the layer the reviews miss: does the delivered logic serve the actual need, end to end, even when code review and functional review both pass? Name any gap between intent and result. -- Demand command output or file evidence, never bare claims. Lean strict: a false alarm costs less than a missed defect. +- Demand command output or file evidence, never bare claims. Report concrete risks with their impact and uncertainty. - When a review skill fits the work, run it and let it write its report; that report is your deliverable and your judgment is what fills it. Never hand-write a parallel prose review beside it. - Return your verdict, findings, and score on top. Hold yourself accountable for whatever you pass. @@ -29,8 +28,8 @@ This is the behavioral baseline. Apply it to every code or diff, and extend it w # Scoring -- If the validator defines weights and thresholds, apply them exactly, and let any hard violation force the score to zero. -- Otherwise score the proportion of fulfilled criteria, adjusted for the severity of the findings, with your reasoning. +- If the supplied review checklist defines weights and thresholds, apply them exactly, and let any hard violation force the score to zero. +- Otherwise score quality and fitness for the need against the review checklist, adjusted for finding severity, with your reasoning. - The pass threshold is the caller's gate, not yours. You report the score; you do not declare pass or fail. # Guardrails diff --git a/plugins/aidd-dev/agents/executor.md b/plugins/aidd-dev/agents/executor.md index e2af667ce..f7244af59 100644 --- a/plugins/aidd-dev/agents/executor.md +++ b/plugins/aidd-dev/agents/executor.md @@ -1,7 +1,6 @@ --- name: executor description: Turns a dispatched task into working, validated code that fits the project. Use when an approved scope must become code. Never plans, never judges its own work. -model: sonnet --- # Role @@ -14,12 +13,13 @@ You are the executor. Your job is to turn a dispatched task into working, valida - Internalize the acceptance criteria before writing anything. If the scope is ambiguous, surface it instead of guessing. - Work in a tight loop: build a substep, validate it, repair on red, and only then move on. Validation passing is the gate, never your own say-so. - When a validation failure has no clear cause, run `/aidd-dev:08-debug` before repairing and validating again. -- Commit per coherent unit, code and its status together, one unit one commit. +- In an assigned phase, execute only that phase. Return checks and changes to the caller before unrelated phases begin. +- Commit only when authorized and when you own the Git index. In parallel work, leave shared Git operations and plan updates to the caller. - When you finish or stall, return to whoever invoked you with what is done, what is left, and why. # Guardrails -- Never author or edit a plan, spec, or acceptance criterion. That authority is the caller's. On any drift, stop and hand it back to be replanned. +- Never change plan content, scope, specs, or acceptance criteria. Update lifecycle status only for plan or phase files assigned by the caller. An assigned-phase executor never updates shared-plan status. On drift, stop and hand it back to be replanned. - Stay strictly in the scope you are handed. Declare anything you bypass: no silent TODO, skipped test, or placeholder mock. - Never judge your own work, and never start a review. The caller handles that. - Never delegate to another agent. diff --git a/plugins/aidd-dev/agents/explorer.md b/plugins/aidd-dev/agents/explorer.md new file mode 100644 index 000000000..1d6bf5c4c --- /dev/null +++ b/plugins/aidd-dev/agents/explorer.md @@ -0,0 +1,24 @@ +--- +name: explorer +description: Explores scoped questions and returns sourced findings. Use when a caller needs evidence before deciding. Never modifies the inspected material. +--- + +# Role + +Explore the assigned question. Return evidence to the caller without deciding implementation scope. + +# Behavior + +- Read relevant code, documentation, and sources. Trace relationships needed to answer the question. +- Separate observed facts from inference. Cite file paths and lines or source URLs. +- Report uncertainties, conflicting evidence, and material risks. +- Stay within the question. Return unresolved questions instead of expanding the task. + +# Outputs + +Return a concise answer, verifiable references, and remaining uncertainties. + +# Guardrails + +- Never modify files or external state. Do not run commands that mutate the inspected material. +- Never implement changes, delegate work, or invoke an orchestrator. diff --git a/plugins/aidd-dev/agents/validator.md b/plugins/aidd-dev/agents/validator.md new file mode 100644 index 000000000..3ed70e33a --- /dev/null +++ b/plugins/aidd-dev/agents/validator.md @@ -0,0 +1,30 @@ +--- +name: validator +description: Validates an identified deliverable against supplied criteria and mandatory checks. Use for independent completion evidence. Never repairs or performs a general quality review. +--- + +# Role + +Validate whether the supplied candidate satisfies its acceptance criteria and mandatory checks. + +# Behavior + +- Identify the candidate revision or artifact before checking it. Confirm the criteria and mandatory checks supplied by the caller or project. +- Use the smallest sufficient observable checks. Run every mandatory check. +- Record PASS, FAIL, or BLOCKED for each criterion and mandatory check with the supporting command output or artifact evidence. +- Mark missing, ambiguous, or unobservable criteria and missing prerequisites BLOCKED. An empty criteria set is blocked even if every command exits zero. +- Never infer completion from an implementer's claim. +- Confirm the candidate did not change during validation. If it changed, report affected evidence as stale. + +# Outputs + +Return the candidate identity, results and evidence, and one overall status: + +- COMPLETE only when every criterion and mandatory check passed on the unchanged identified candidate. +- BLOCKED when criteria or prerequisites are missing, criteria are ambiguous or unobservable, or candidate evidence is stale. +- INCOMPLETE when checks failed and no blocker prevents a reliable conclusion. + +# Guardrails + +- Never repair the candidate or change its criteria. Checks may create their normal temporary artifacts, but must not rewrite the deliverable. +- Never perform a general quality review, delegate work, or invoke an orchestrator. diff --git a/plugins/aidd-dev/skills/01-plan/SKILL.md b/plugins/aidd-dev/skills/01-plan/SKILL.md index 1bbb438ae..b0609c7ab 100644 --- a/plugins/aidd-dev/skills/01-plan/SKILL.md +++ b/plugins/aidd-dev/skills/01-plan/SKILL.md @@ -6,19 +6,31 @@ argument-hint: request | ticket | file # Skill: plan -Turn a gathered source into an implementation plan and its phase files. Never writes code. +```mermaid +flowchart TD + Request([request, ticket, or file]) --> gather + gather --> explore + explore -- UI --> wireframe + explore -- no UI --> plan + wireframe --> plan + plan -- revision needed --> plan + plan --> Ready([plan ready]) +``` ## Actions -| # | Action | Role | Input | -| --- | ----------- | ---------------------------------------------------- | -------------------------- | -| 01 | `gather` | Collect and restate the source | user request | -| 02 | `explore` | Read the codebase for projection, rules, feasibility | gathered source | -| 03 | `wireframe` | Sketch a screen at low fidelity, frontend only | source + explore context | -| 04 | `plan` | Break into phases, write the plan and phase files | explore output + wireframe | +Read only the next matching numbered action file in `actions/`. + +| Action | Does | +| --- | --- | +| gather | collect and restate the source | +| explore | ground the projection, rules, and feasibility | +| wireframe | sketch frontend screens at low fidelity | +| plan | write and review the plan and phase files | -Run them in order, `01 → 04`. The plan is the culmination. Skip `03` when there is no UI. -Before running an action, read its file in `actions/`, not only the table or assets. +## Transversal rules + +- Planning never writes application code. Once the plan and its phase files are written, and only then, run: @@ -26,12 +38,6 @@ Once the plan and its phase files are written, and only then, run: echo "aidd:step-end aidd-dev:01-plan" ``` -This is the one thing about a step nothing else can supply. No host reports when a skill's -work finished — a skill call's own result comes back in a tenth of a second, which is the -dispatch, not the completion — so a measurement that never hears this ends the step at the -next pause and credits planning with one turn out of however many it took. The framework -repository documents the run journal this writes into, in `aidd_docs/runs/README.md`. - ## References - `references/wireframe-conventions.md`: how to draw the ASCII wireframe a screen needs. diff --git a/plugins/aidd-dev/skills/01-plan/actions/02-explore.md b/plugins/aidd-dev/skills/01-plan/actions/02-explore.md index 33a6916d5..f906d5301 100644 --- a/plugins/aidd-dev/skills/01-plan/actions/02-explore.md +++ b/plugins/aidd-dev/skills/01-plan/actions/02-explore.md @@ -12,12 +12,17 @@ The architecture projection (files to modify, create, delete, each with a one-li ## Process -1. **Read.** Explore the code the source touches. Build the projection and list the infrastructure assumptions. +1. **Read.** Explore the code the source touches and build the projection with its infrastructure assumptions. + - The primary caller may delegate independent, bounded read-only questions to available explorers when useful. Each returns references and unresolved questions. + - Reconcile their findings against the source before planning. Resolve conflicting claims or retain the uncertainty. An isolated agent never delegates again. 2. **Check.** Verify against the official docs or the in-repo code. Keep each source and what it settled. Flag blockers and risks. 3. **Select.** Keep the project rules that apply to the projection. ## Test -- The projection lists files to modify, create, and delete, each with a one-line reason. -- Every feasibility check records its source and what it settled. -- The applicable rules are identified and justified, or none apply. +| Case | Pass | +| --- | --- | +| The exploration completes | The projection names files to modify, create, and delete with reasons; applicable rules are justified or none apply. | +| A feasibility claim is made | Its source and what it settled are recorded. | +| Exploration is delegated | Returned references and unresolved questions are reconciled into the projection and risks. | +| Sources disagree | The conflict is resolved with evidence or remains explicit as uncertainty. | diff --git a/plugins/aidd-dev/skills/01-plan/references/plan-status.md b/plugins/aidd-dev/skills/01-plan/references/plan-status.md index 51e98bf1e..59442bb8b 100644 --- a/plugins/aidd-dev/skills/01-plan/references/plan-status.md +++ b/plugins/aidd-dev/skills/01-plan/references/plan-status.md @@ -20,4 +20,4 @@ The plan's `status` frontmatter field tracks its lifecycle for kanban views. The - Linear: `pending → in-progress → implemented → reviewed`. `blocked` is reachable from any active state. - Review reject (`iterate` / `changes-requested`) does NOT set `reviewed`. The plan stays `implemented` while the loop fixes the diff, not the plan. - `implemented` ≠ reviewed. Only the review layer sets `reviewed`. -- Workers never write `status`; only plan creation and the orchestration layers do. +- Assigned phase workers never write the plan status. They may update only their own phase status; the whole-plan owner updates the plan. diff --git a/plugins/aidd-dev/skills/02-implement/SKILL.md b/plugins/aidd-dev/skills/02-implement/SKILL.md index dd77f0fd3..e07d2af44 100644 --- a/plugins/aidd-dev/skills/02-implement/SKILL.md +++ b/plugins/aidd-dev/skills/02-implement/SKILL.md @@ -1,29 +1,44 @@ --- name: 02-implement -description: Write an existing plan's code, phase by phase, until every acceptance criterion holds. Use when a plan exists and needs implementing. Do NOT use to write a plan, review a diff. -argument-hint: plan +description: Implements an existing plan or an assigned phase until its acceptance criteria hold. Use when a plan or bounded phase needs implementing. Not for writing a plan or reviewing a diff. +argument-hint: plan | phase --- # Skill: implement -Run an existing plan to write its code, one phase at a time, until every acceptance criterion holds. +```mermaid +flowchart TD + Whole([whole plan]) --> prepare + Assigned([assigned phase]) --> execute + prepare --> execute + execute -- check failed, repair --> execute + execute -- more ready phases --> execute + execute -- assigned phase complete --> Returned([return phase and evidence]) + execute -- whole plan complete --> finalize + finalize -- validation failed, repair affected scope --> execute + finalize --> Implemented([implemented]) + prepare -- plan missing --> Missing([stop]) + execute -- blocked or drift --> Stopped([report blocker or replan needed]) +``` ## Actions -| # | Action | Role | Input | -| --- | ---------- | ----------------------------------------------- | ------------- | -| 01 | `prepare` | Resolve the plan, branch, mark it in-progress | a plan path | -| 02 | `execute` | Loop the phases, code and assert each | prepared plan | -| 03 | `finalize` | Verify and mark the plan implemented | coded phases | +Read only the next matching numbered action file in `actions/`. -Run them in order, `01 → 03`. -Before running an action, read its file in `actions/`, not only the table or assets. +| Action | Does | +| --- | --- | +| prepare | resolve the whole plan and prepare its branch | +| execute | implement and validate the selected scope | +| finalize | verify the integrated plan and mark it implemented | ## Transversal rules -- Status: drive the plan through `pending → in-progress → implemented` (or `blocked`), and each phase through `pending → in-progress → done`. The `in-progress` values are runtime markers; only `done` and `implemented` need to land in a commit. -- Commits: one commit per phase, its code together with the phase reaching `done`, plus a final commit for the plan reaching `implemented`. Never leave the tree dirty at a phase boundary. Do not scatter separate `in-progress` status commits: one context now owns both code and status, so there is nothing to guard against. +- Supplying a whole plan assigns lifecycle-status ownership of that plan and its phases to the whole-plan runner. Supplying an assigned phase grants only that phase's lifecycle-status ownership. Neither grant permits changes to scope, specifications, or criteria. +- A whole-plan run owns integration and completion verification. An assigned-phase run enters execute directly and returns without prepare or finalize. The primary caller retains final acceptance. +- Phase status follows `pending → in-progress → done`. The whole-plan owner drives `pending → in-progress → implemented` or `blocked`. Runtime markers need no separate commit. +- Follow the caller's commit policy. When commits are authorized, commit each phase's code with its own `done` status and the final plan status separately. Keep unrelated changes out of these commits. +- Isolated agents never spawn agents. Only the primary caller may delegate bounded work using available host capabilities. ## References -- `references/blocked.md`: the conditions that make a plan `blocked` and need a human. +- `references/blocked.md`: conditions requiring a human. diff --git a/plugins/aidd-dev/skills/02-implement/actions/01-prepare.md b/plugins/aidd-dev/skills/02-implement/actions/01-prepare.md index 7e99042de..8171926c0 100644 --- a/plugins/aidd-dev/skills/02-implement/actions/01-prepare.md +++ b/plugins/aidd-dev/skills/02-implement/actions/01-prepare.md @@ -4,7 +4,7 @@ Resolve the plan, put the workspace on a feature branch, and mark the plan in-pr ## Input -A plan, passed as arguments as a path or inline content. +A whole plan, passed as arguments as a path or inline content. ## Output @@ -14,10 +14,11 @@ The resolved plan on a feature branch with its frontmatter `status: in-progress` 1. **Resolve.** Resolve the plan from the arguments. A path must exist and be readable. With neither a readable file nor inline content, stop with `plan not found at `. Never fabricate a plan. 2. **Branch.** On the default branch, create a feature branch and announce it. On a non-default branch, keep it. -3. **Mark.** Set the plan frontmatter `status: in-progress` as a runtime marker. No separate commit: it rides into the first phase commit, or into the `implemented` commit if there is no phase to code. +3. **Mark.** Set the plan frontmatter `status: in-progress` as a runtime marker. Leave shared plan updates to the whole-plan owner; they follow the caller's commit policy. ## Test -- A missing or unreadable plan with no inline content stops with `plan not found at `, and no plan is fabricated. -- The current branch is not the default branch. -- The plan frontmatter reads `status: in-progress`. +| Case | Pass | +| --- | --- | +| No readable plan or inline content resolves | Execution stops with `plan not found at `; no plan is fabricated. | +| Preparation succeeds | The current branch is not the default branch and the plan status is in-progress. | diff --git a/plugins/aidd-dev/skills/02-implement/actions/02-execute.md b/plugins/aidd-dev/skills/02-implement/actions/02-execute.md index 2c531ffb4..952d59fe1 100644 --- a/plugins/aidd-dev/skills/02-implement/actions/02-execute.md +++ b/plugins/aidd-dev/skills/02-implement/actions/02-execute.md @@ -1,26 +1,39 @@ # 02 - Execute -Loop the plan's phases in order, coding each until every acceptance criterion holds. - ## Input -The prepared plan on its feature branch, from `01-prepare`. +A prepared whole plan, or an assigned phase whose file is included in the assigned scope, with its plan context, completed prerequisites, acceptance criteria, checkout, and commit policy. ## Output -Every phase coded, asserted, and its frontmatter marked `status: done`, with the commits on the branch. Or a stop at `status: blocked` when a human is needed, or a `replan needed` report on any drift from the plan. +The selected phases implemented with passing checks, `status: done`, and evidence identifying the checked revision. Or a blocker or `replan needed` report. ## Process -1. **Open.** Walk the phases in order. In a feature folder each is a `phase-.md` next to `plan.md`. Set its `status: in-progress` as a runtime marker; no commit yet. -2. **Code.** Build the phase scope against its acceptance criteria. -3. **Assert.** Assert the phase against its acceptance criteria. On failure, repair and repeat. The gate is the assertion passing, not a self-report. Once it passes, set `status: done` and commit the phase as one unit, its code and its status together. -4. **Guard.** Stop the loop on either condition: - - **Blocked** (see [blocked.md](../references/blocked.md)): set the plan `status: blocked`, commit, stop. - - **Drift**: any mismatch with the plan, trivial or substantive, stop and report `replan needed: `. Never rewrite the plan; replanning is the caller's job. +1. **Select.** Resolve the execution scope and its prerequisites before changing files. + - Assigned phase: implement only that phase. Require a distinct checkout and nonconflicting validation resources when other executors run concurrently. Do not restart the plan, update its shared status, or run finalization. + - Whole plan: select phases whose `Depends on` prerequisites are done and integrated. Check file projections, shared contracts, and mutable validation resources before the primary caller dispatches a parallel batch to available executors. Give each ownership of its phase file for lifecycle-status updates only, completed prerequisites, criteria, isolated checkout, resources, and commit policy. + - Execute serially when isolation is unavailable or independence is uncertain. A plan without declared dependencies runs in phase order. + - Report `replan needed` for missing or contradictory prerequisites, or when unfinished phases have no ready phase; never skip them to declare completion. +2. **Code.** Mark the selected phase `in-progress` and implement only its projection against its acceptance criteria. +3. **Assert.** Run the relevant phase checks, repair failures, and repeat until they pass. + - Then mark the phase `done` and deliver its code, phase status, check commands, results, and checked revision under the caller's commit policy. + - The whole-plan owner integrates returned work before considering a dependency complete. Run checks for interactions changed by integration; reserve full plan validation for finalize. Select the next ready phases until all are done. +4. **Guard.** Stop affected work on a blocker or any scope drift. + - **Blocked:** apply [blocked.md](../references/blocked.md); an assigned executor reports to the caller, while the whole-plan owner marks the plan `blocked`. + - **Drift:** report `replan needed: ` without rewriting the plan or criteria. The caller decides how to revise the plan before resuming dependent work. ## Test -- A phase reaches `status: done` only after assert passes against its acceptance criteria, in one commit with its code (`git status --short` shows no dangling phase edits). -- The branch holds one commit per phase; there are no separate `in-progress` status commits. -- A blocker leaves the plan `status: blocked` with no later phase run. +| Case | Pass | +| --- | --- | +| An assigned phase runs | Only its code and owned phase lifecycle status change; prepare, shared plan updates, other phases, and finalize are not run. | +| A whole-plan executor runs | It updates only lifecycle statuses in supplied plan and phase files; scope, specifications, and criteria remain unchanged. | +| A prerequisite is unfinished | Its dependent phase is not started. | +| Prerequisites are missing or contradictory | Execution stops for replanning without marking unfinished phases done. | +| A parallel batch runs | File changes and mutable validation resources do not conflict; executors use distinct checkouts and Git indexes. | +| Isolation or independence is uncertain | Execution is serial. | +| The plan has no dependency declarations | Phases run in their original order. | +| A phase reaches done | Its criteria pass and the returned evidence identifies the checked revision. | +| A returned phase has dependents | Its changes are integrated before any dependent starts. | +| A blocker or scope drift occurs | Affected work stops; an assigned executor reports without rewriting shared plan state. | diff --git a/plugins/aidd-dev/skills/02-implement/actions/03-finalize.md b/plugins/aidd-dev/skills/02-implement/actions/03-finalize.md index 2943bc426..bf5ccfb19 100644 --- a/plugins/aidd-dev/skills/02-implement/actions/03-finalize.md +++ b/plugins/aidd-dev/skills/02-implement/actions/03-finalize.md @@ -12,10 +12,17 @@ The feature validated green with the plan frontmatter `status: implemented`. ## Process -1. **Verify.** Run the plan's validation commands and tests. Never format code, never run dev mode. -2. **Mark.** Every phase done and validation green, set the plan `status: implemented` and commit it. +1. **Verify.** Verify every plan-level acceptance criterion and required validation against the integrated candidate. + - Phase checks alone do not establish that the combined workflow works. + - Reuse a passing result only when it covers the same candidate and required scope; rerun checks invalidated by later changes or integration. Never format code or run dev mode. + - On failure, return the affected scope to execution and verify the repaired candidate before marking completion. +2. **Mark.** Set the plan `status: implemented` only when every phase is done and integrated validation is green, then deliver under the caller's commit policy. ## Test -- The validation commands exit zero. -- The plan reads `status: implemented`, committed (`git status --short` shows it clean). +| Case | Pass | +| --- | --- | +| Finalization succeeds | Every phase is done and the required validation covers the integrated candidate with passing results. | +| A previous result is reused | Its candidate and required scope match; changed candidates invalidate affected checks. | +| Validation fails | The plan is not marked implemented; affected work returns for repair. | +| The plan reaches implemented | Its status is delivered under the caller's commit policy. | diff --git a/plugins/aidd-dev/skills/02-implement/references/blocked.md b/plugins/aidd-dev/skills/02-implement/references/blocked.md index 505a33899..42c94f6a1 100644 --- a/plugins/aidd-dev/skills/02-implement/references/blocked.md +++ b/plugins/aidd-dev/skills/02-implement/references/blocked.md @@ -5,6 +5,6 @@ description: Conditions that make a plan blocked (needs a human). # When a plan is blocked -`blocked` means implementation cannot proceed and only a human can unblock it. Stop, set `status: blocked`, and escalate. +`blocked` means implementation cannot proceed and only a human can unblock it. Stop and escalate to the whole-plan owner, who sets the plan `status: blocked`. Physically impossible for the AI (no retry helps): real credit-card payment; human login (Google OAuth, Apple Face/Touch ID); a secret the AI cannot read; anything behind hardware or 2FA. diff --git a/plugins/aidd-orchestrator/skills/01-sdlc/SKILL.md b/plugins/aidd-orchestrator/skills/01-sdlc/SKILL.md index 24c3114f3..354b0c7a4 100644 --- a/plugins/aidd-orchestrator/skills/01-sdlc/SKILL.md +++ b/plugins/aidd-orchestrator/skills/01-sdlc/SKILL.md @@ -8,9 +8,9 @@ argument-hint: request ## Behavior -Operate autonomously from the request to a draft pull request: decide and act without confirmation, asking only before spending money, taking an irreversible action, or making a decision that requires user authority. Read only the current zone reference. Verify that every named provider is installed before calling it. +Operate autonomously from the request to a draft pull request: decide and act without confirmation, asking only before spending money, taking an irreversible action, or making a decision that requires user authority. Read only the current zone reference. Discover providers from installed skill and agent descriptions by responsibility. Verify their availability and contracts before dispatch; addresses in diagrams illustrate current providers. -Spawn specialized agents for isolated work. Parallelize independent work when it is faster. Give each agent one focused task that a smaller model can execute. Repeat the responsible zone when delegated work returns an actionable gap. +Spawn specialized agents for isolated work. Parallelize independent work when it is faster. Give each leaf agent one focused task. Keep model selection outside the role contract. Repeat the responsible zone when delegated work returns an actionable gap. ```mermaid --- diff --git a/plugins/aidd-orchestrator/skills/01-sdlc/references/02-deliver.md b/plugins/aidd-orchestrator/skills/01-sdlc/references/02-deliver.md index c2b1a817c..d7b8192fd 100644 --- a/plugins/aidd-orchestrator/skills/01-sdlc/references/02-deliver.md +++ b/plugins/aidd-orchestrator/skills/01-sdlc/references/02-deliver.md @@ -2,9 +2,13 @@ ## Behavior -Turn the contract into a proportional plan, then give one executor the plan. The executor implements it and calls the validation skills, which own their checks and repair loops. Include architecture conformance whenever the project documents architecture. Run a required end-to-end journey after every other validation. +Turn the contract into a proportional plan. Delegate bounded read-only exploration when useful and reconcile sources and unknowns before planning. -Commit and push the validated work through the commit skill. Send only the clean committed candidate to Check. +Own preparation, shared plan status, dependencies, integration, and finalization. Assign ready, independent phases to executors in distinct checkouts with nonconflicting validation resources. Include each assigned phase file in its scope for lifecycle-status updates only, alongside plan context, criteria, completed prerequisites, and commit policy. Run sequentially when isolation is unavailable or independence is uncertain; legacy plans retain their phase order. For a sequential whole-plan executor, grant lifecycle-status ownership of the plan and all its phases while retaining acceptance; never grant changes to scope, specifications, or criteria. + +Executors implement, validate, and repair only their assigned scope without further delegation. Include architecture conformance when documented. Integrate each returned phase before starting its dependents. Finalize against the integrated candidate, including any required end-to-end journey last. Preserve passing evidence only when its candidate and scope still match. + +Commit and push through the commit capability. Send the clean committed candidate and its validation evidence to Check. ```mermaid --- @@ -20,9 +24,11 @@ flowchart TD subgraph ExecuteStage["Execute and validate the plan"] direction TB + Dispatch["Caller selects ready phases"] Executor(["@aidd-dev:executor"]) Implement["/aidd-dev:02-implement"] Assert["/aidd-dev:03-assert"] + Integrate["Integrate phases and finalize plan"] Test["/aidd-dev:06-test"] Commit["/aidd-vcs:01-commit"] end @@ -35,11 +41,14 @@ flowchart TD Contract --> Plan Plan --> PlanArtifact - PlanArtifact --> Executor + PlanArtifact --> Dispatch + Dispatch -- "Isolated executors for independent phases; serial otherwise." --> Executor Executor --> Implement Implement --> Assert - Assert -- "When no end-to-end journey is required, commit the result." --> Commit - Assert -- "When an end-to-end journey is required, run it last." --> Test + Assert --> Integrate + Integrate -- "More ready phases." --> Dispatch + Integrate -- "No required end-to-end journey." --> Commit + Integrate -- "Run required end-to-end journey last." --> Test Test -- "After the journey succeeds, commit the result." --> Commit Test -- "Return a failed journey for repair." --> Executor Commit --> CommittedCandidate diff --git a/plugins/aidd-orchestrator/skills/01-sdlc/references/03-check.md b/plugins/aidd-orchestrator/skills/01-sdlc/references/03-check.md index c871e419f..38b042aa5 100644 --- a/plugins/aidd-orchestrator/skills/01-sdlc/references/03-check.md +++ b/plugins/aidd-orchestrator/skills/01-sdlc/references/03-check.md @@ -2,7 +2,9 @@ ## Behavior -Use one fresh checker, independent from implementation, to review the candidate against the contract, plan, and validation evidence. After the review clears, the same checker challenges whether the real outcome is trustworthy and serves the user. +Use a fresh validator independent from implementation to verify the identified committed candidate against the contract, plan criteria, and mandatory checks. Require PASS, FAIL, or BLOCKED per criterion with evidence. The validator does not repair. + +Only after validation passes, use a fresh checker to review quality, risks, and fitness against the contract, plan, and validation evidence. Repeat targeted checks only when evidence is missing, inconsistent, or stale. After review clears, the same checker challenges the outcome. Any repaired candidate returns to independent validation; neither judgment carries forward automatically. Use product or contract findings as the next Frame source. Dispatch independent implementation findings through Todo and keep dependent repairs together in Deliver. Re-enter Check after every new candidate. Open the draft pull request when the checker returns no actionable finding. @@ -17,6 +19,7 @@ flowchart TD Plan["$plan"] CommittedCandidate["$committed_candidate"] ValidationReports["$validation_reports"] + Validator(["@aidd-dev:validator"]) Checker(["@aidd-dev:checker"]) Review["/aidd-dev:05-review"] end @@ -40,10 +43,12 @@ flowchart TD PullRequestUrl["$pull_request_url"] end - Contract --> Checker - Plan --> Checker - CommittedCandidate --> Checker - ValidationReports --> Checker + Contract --> Validator + Plan --> Validator + CommittedCandidate --> Validator + ValidationReports --> Validator + Validator -- "All criteria pass with evidence." --> Checker + Validator -- "Fail or blocked." --> Findings Checker --> Review Review -- "Return actionable review findings." --> Findings Review -- "When the review clears, challenge the outcome." --> Challenge @@ -61,7 +66,7 @@ flowchart TD classDef zone fill:#F1F5F9,stroke:#64748B,color:#0F172A,stroke-width:2px class Review,Challenge,Todo,PullRequest skill - class Checker agent + class Checker,Validator agent class Contract,Plan,CommittedCandidate,ValidationReports,Findings,PullRequestUrl artifact class Frame,Deliver zone ``` From e00f124c59d3fe4ca44c173355f04d5ad809d97a Mon Sep 17 00:00:00 2001 From: alexsoyes Date: Wed, 14 Oct 2026 13:48:08 +0800 Subject: [PATCH 04/73] fix(framework): sync opencode agents and reject incomplete reloads Install every selected native agent and preflight complete build output before replacing installed content. Surface build and installation failures instead of claiming success. Refs #983 --- aidd_docs/memory/deployment.md | 21 ++++ scripts/__tests__/dev-sync.test.js | 189 ++++++++++++++++++++++++++++- scripts/dev-sync.sh | 55 +++++++-- 3 files changed, 255 insertions(+), 10 deletions(-) diff --git a/aidd_docs/memory/deployment.md b/aidd_docs/memory/deployment.md index 901f9cdd9..cd8af01d2 100644 --- a/aidd_docs/memory/deployment.md +++ b/aidd_docs/memory/deployment.md @@ -56,6 +56,27 @@ Config: `release-please-config.json`, eleven packages. Manifest: `.release-pleas - `build-per-tool` builds the CLI from this run's own checkout (`cd cli && pnpm install && pnpm build`, then `node cli/dist/cli.js translate`) rather than pinning a published version — no version to bump, and nothing can go stale the way the old `@ai-driven-dev/cli@5.1.1 framework build` pin did once `framework build` was replaced by `translate`. +## Local reload + +`make reload` refreshes every plugin. `scripts/dev-sync.sh` copies built OpenCode skills and +namespaced agents into the global directories, replacing only selected plugin namespaces. +Missing expected build files fail before changing installed OpenCode content. A managed +OpenCode host keeps its fixed-purpose `aidd-opencode-reload` helper. + +OpenCode V2 documents global agents at `~/.config/opencode/agents/`, filename-based agent +names, and `mode: subagent`. Native restrictions use a `permissions` list with `action`, +`resource`, and `effect`; `edit` covers write, edit and patch, `shell` gates commands, and +`subagent` gates delegation. Source: , read 2026-10-14. +V2.0.28 also migrates legacy Markdown fields during discovery: +, +read 2026-10-14. After reload, `opencode debug agents` lists installed names; file presence +alone does not establish discovery, invocation, or permission enforcement. + +For an OpenCode V2.0.28 subprocess probe, set both its working directory and `PWD` to the +fixture: `run` prefers `process.env.PWD` over `process.cwd()` and changes directory to it. +Source: , +read 2026-10-14. + ## Monitoring None. Failures surface as a red run; `back-merge.yml` opens a tracking issue when it cannot push, so drift is never silent. diff --git a/scripts/__tests__/dev-sync.test.js b/scripts/__tests__/dev-sync.test.js index 9c37bbf01..2c0fcf9ba 100644 --- a/scripts/__tests__/dev-sync.test.js +++ b/scripts/__tests__/dev-sync.test.js @@ -6,12 +6,32 @@ const { delimiter, join, resolve } = require("node:path"); const test = require("node:test"); const repo = resolve(__dirname, "../.."); +const devAgents = ["checker.md", "executor.md"]; +const buildDevAgents = devAgents.map((name) => `printf '%s\\n' 'updated agent' > "$out/.opencode/agents/aidd-dev-${name}"`).join("\n"); function executable(path, body) { writeFileSync(path, `#!/bin/sh\nset -eu\n${body}\n`); chmodSync(path, 0o755); } +function fixture(home) { + const source = join(home, "framework"); + if (!existsSync(source)) { + for (const [plugin, skill, agents] of [["aidd-dev", "01-plan", devAgents], ["aidd-pm", "03-prd", []]]) { + const pluginDir = join(source, "plugins", plugin); + mkdirSync(join(pluginDir, ".claude-plugin"), { recursive: true }); + writeFileSync(join(pluginDir, ".claude-plugin/plugin.json"), "{}\n"); + mkdirSync(join(pluginDir, "skills", skill), { recursive: true }); + writeFileSync(join(pluginDir, "skills", skill, "SKILL.md"), "source skill\n"); + for (const name of agents) { + mkdirSync(join(pluginDir, "agents"), { recursive: true }); + writeFileSync(join(pluginDir, "agents", name), "source agent\n"); + } + } + } + return source; +} + /** On POSIX, nothing but the stubs and the platform's own utilities, so a real `opencode` or * `claude` installed on the machine running these tests can never answer in their place. * Windows has neither directory, and the utilities `dev-sync.sh` calls live wherever Git for @@ -29,8 +49,13 @@ function runSync(fakeBin, home, args = ["all"]) { ...process.env, PATH: [fakeBin, BASE_PATH].join(delimiter), HOME: home, + FW: fixture(home), BUILD: join(home, "build"), + CODEX_CACHE: join(home, ".codex/plugins/cache"), + CLAUDE_CACHE: join(home, ".claude/plugins/cache"), + CODEX_AGENTS: join(home, ".codex/agents"), OPENCODE_SKILLS: join(home, ".config/opencode/skills"), + OPENCODE_AGENTS: join(home, ".config/opencode/agents"), }, encoding: "utf8", }); @@ -71,6 +96,12 @@ for (const layout of ["flat", "nested"]) { const unrelated = join(home, ".config/opencode/skills/aidd-pm/03-prd/SKILL.md"); mkdirSync(join(home, ".config/opencode/skills/aidd-pm/03-prd"), { recursive: true }); writeFileSync(unrelated, "keep\n"); + const agentDir = join(home, ".config/opencode/agents"); + mkdirSync(agentDir, { recursive: true }); + writeFileSync(join(agentDir, "aidd-dev-checker.md"), "old agent\n"); + writeFileSync(join(agentDir, "aidd-dev-removed.md"), "stale\n"); + writeFileSync(join(agentDir, "personal.md"), "keep\n"); + writeFileSync(join(agentDir, "aidd-pm-review.md"), "keep\n"); executable(join(fakeBin, "opencode"), "exit 0"); const skillName = layout === "nested" ? "aidd-dev/01-plan" : "aidd-dev-01-plan"; executable( @@ -84,7 +115,9 @@ skill="$out/.opencode/skills/${skillName}" mkdir -p "$skill/actions" "$skill/assets" printf '%s\n' '---' 'name: aidd-dev-01-plan' 'description: test' '---' > "$skill/SKILL.md" printf '%s\n' 'updated action' > "$skill/actions/04-plan.md" -printf '%s\n' 'updated template' > "$skill/assets/plan-template.md"`, +printf '%s\n' 'updated template' > "$skill/assets/plan-template.md" +mkdir -p "$out/.opencode/agents" +${buildDevAgents}`, ); const result = runSync(fakeBin, home, ["aidd-dev"]); @@ -97,6 +130,13 @@ printf '%s\n' 'updated template' > "$skill/assets/plan-template.md"`, assert.equal(existsSync(join(home, ".config/opencode/skills/aidd-dev/removed")), false); assert.equal(readFileSync(unrelated, "utf8"), "keep\n"); assert.match(result.stdout, /install opencode\s+skills:ok/); + for (const name of devAgents) { + assert.equal(readFileSync(join(agentDir, `aidd-dev-${name}`), "utf8"), "updated agent\n"); + } + assert.equal(existsSync(join(agentDir, "aidd-dev-removed.md")), false); + assert.equal(readFileSync(join(agentDir, "personal.md"), "utf8"), "keep\n"); + assert.equal(readFileSync(join(agentDir, "aidd-pm-review.md"), "utf8"), "keep\n"); + assert.match(result.stdout, /agents:ok/); } finally { rmSync(root, { recursive: true, force: true }); } @@ -117,10 +157,155 @@ test("local OpenCode reload rejects missing selected skills before removing inst const result = runSync(fakeBin, home, ["aidd-dev"]); assert.notEqual(result.status, 0); - assert.match(result.stderr, /no built OpenCode skills for aidd-dev/); + assert.match(result.stderr, /no built OpenCode skill for aidd-dev-01-plan/); assert.doesNotMatch(result.stdout, /skills:ok/); assert.equal(readFileSync(installed, "utf8"), "keep\n"); } finally { rmSync(root, { recursive: true, force: true }); } }); + +test("local OpenCode reload rejects a missing agent before changing installed content", () => { + const root = mkdtempSync(join(tmpdir(), "aidd-dev-sync-agent-missing-")); + try { + const fakeBin = join(root, "bin"); + const home = join(root, "home"); + mkdirSync(fakeBin); + const skillDir = join(home, ".config/opencode/skills/aidd-dev-01-plan"); + const agentDir = join(home, ".config/opencode/agents"); + mkdirSync(skillDir, { recursive: true }); + mkdirSync(agentDir, { recursive: true }); + writeFileSync(join(skillDir, "SKILL.md"), "keep skill\n"); + writeFileSync(join(agentDir, "aidd-dev-checker.md"), "keep agent\n"); + executable(join(fakeBin, "opencode"), "exit 0"); + const remainingAgents = devAgents.filter((name) => name !== "checker.md").map((name) => + `printf '%s\\n' 'agent' > "$out/.opencode/agents/aidd-dev-${name}"`, + ).join("\n"); + executable(join(fakeBin, "npx"), String.raw`out="" +while [ "$#" -gt 0 ]; do + if [ "$1" = "--out" ]; then shift; out=$1; fi + shift +done +mkdir -p "$out/.opencode/skills/aidd-dev-01-plan" +printf '%s\n' 'new skill' > "$out/.opencode/skills/aidd-dev-01-plan/SKILL.md" +mkdir -p "$out/.opencode/agents" +${remainingAgents}`); + + const result = runSync(fakeBin, home, ["aidd-dev"]); + assert.notEqual(result.status, 0); + assert.match(result.stderr, /no built OpenCode agent for aidd-dev-/); + assert.doesNotMatch(result.stdout, /skills:ok|agents:ok/); + assert.equal(readFileSync(join(skillDir, "SKILL.md"), "utf8"), "keep skill\n"); + assert.equal(readFileSync(join(agentDir, "aidd-dev-checker.md"), "utf8"), "keep agent\n"); + } finally { + rmSync(root, { recursive: true, force: true }); + } +}); + +test("default OpenCode reload installs every plugin's skills and agents", () => { + const root = mkdtempSync(join(tmpdir(), "aidd-dev-sync-all-")); + try { + const fakeBin = join(root, "bin"); + const home = join(root, "home"); + mkdirSync(fakeBin); + mkdirSync(home); + const skills = ["aidd-dev-01-plan", "aidd-pm-03-prd"]; + const agents = devAgents.map((name) => `aidd-dev-${name}`); + const buildSkills = skills.map((name) => `mkdir -p "$out/.opencode/skills/${name}"\nprintf '%s\\n' 'skill' > "$out/.opencode/skills/${name}/SKILL.md"`).join("\n"); + const buildAgents = agents.map((name) => `printf '%s\\n' 'agent' > "$out/.opencode/agents/${name}"`).join("\n"); + executable(join(fakeBin, "opencode"), "exit 0"); + executable(join(fakeBin, "npx"), `out="" +while [ "$#" -gt 0 ]; do + if [ "$1" = "--out" ]; then shift; out=$1; fi + shift +done +mkdir -p "$out/.opencode/agents" +${buildSkills} +${buildAgents}`); + + const result = runSync(fakeBin, home, []); + assert.equal(result.status, 0, result.stderr); + for (const skill of skills) { + assert.equal(readFileSync(join(home, ".config/opencode/skills", `${skill}/SKILL.md`), "utf8"), "skill\n"); + } + for (const agent of agents) { + assert.equal(readFileSync(join(home, ".config/opencode/agents", agent), "utf8"), "agent\n"); + } + assert.match(result.stdout, /skills:ok agents:ok/); + } finally { + rmSync(root, { recursive: true, force: true }); + } +}); + +for (const badOutput of ["missing", "empty"]) { + test(`OpenCode rejects ${badOutput} expected skill output despite another built skill`, () => { + const root = mkdtempSync(join(tmpdir(), "aidd-dev-sync-partial-")); + try { + const fakeBin = join(root, "bin"); + const home = join(root, "home"); + mkdirSync(fakeBin); + const source = fixture(home); + const second = join(source, "plugins/aidd-dev/skills/02-implement"); + mkdirSync(second); + writeFileSync(join(second, "SKILL.md"), "source skill\n"); + const installed = join(home, ".config/opencode/skills/aidd-dev-02-implement"); + mkdirSync(installed, { recursive: true }); + writeFileSync(join(installed, "SKILL.md"), "keep\n"); + executable(join(fakeBin, "opencode"), "exit 0"); + executable(join(fakeBin, "npx"), String.raw`out="" +while [ "$#" -gt 0 ]; do + if [ "$1" = "--out" ]; then shift; out=$1; fi + shift +done +mkdir -p "$out/.opencode/skills/aidd-dev-01-plan" "$out/.opencode/agents" +printf '%s\n' 'skill' > "$out/.opencode/skills/aidd-dev-01-plan/SKILL.md" +${buildDevAgents} +${badOutput === "empty" ? 'mkdir -p "$out/.opencode/skills/aidd-dev-02-implement"; touch "$out/.opencode/skills/aidd-dev-02-implement/SKILL.md"' : ""}`); + const result = runSync(fakeBin, home, ["aidd-dev"]); + assert.notEqual(result.status, 0); + assert.match(result.stderr, /no built OpenCode skill for aidd-dev-02-implement/); + assert.equal(readFileSync(join(installed, "SKILL.md"), "utf8"), "keep\n"); + assert.doesNotMatch(result.stdout, /skills:ok|Done\./); + } finally { + rmSync(root, { recursive: true, force: true }); + } + }); +} + +for (const host of ["opencode", "codex"]) { + test(`reload fails when the installed ${host} host's build fails`, () => { + const root = mkdtempSync(join(tmpdir(), "aidd-dev-sync-build-failed-")); + try { + const fakeBin = join(root, "bin"); + const home = join(root, "home"); + mkdirSync(fakeBin); + executable(join(fakeBin, host), "exit 0"); + executable(join(fakeBin, "npx"), "exit 7"); + const result = runSync(fakeBin, home, ["aidd-dev"]); + assert.notEqual(result.status, 0); + assert.match(result.stderr, new RegExp(`${host} build failed`)); + assert.doesNotMatch(result.stdout, /Done\./); + } finally { + rmSync(root, { recursive: true, force: true }); + } + }); +} + +for (const host of ["codex", "claude"]) { + test(`reload fails when the installed ${host} host rejects a plugin`, () => { + const root = mkdtempSync(join(tmpdir(), "aidd-dev-sync-install-failed-")); + try { + const fakeBin = join(root, "bin"); + const home = join(root, "home"); + mkdirSync(fakeBin); + executable(join(fakeBin, host), `if [ "$1" = plugin ] && [ "$2" = ${host === "codex" ? "add" : "install"} ]; then exit 8; fi\nexit 0`); + executable(join(fakeBin, "npx"), "exit 0"); + const result = runSync(fakeBin, home, ["aidd-dev"]); + assert.notEqual(result.status, 0); + assert.match(result.stderr, /plugin install failed for aidd-dev/); + assert.doesNotMatch(result.stdout, /Done\./); + } finally { + rmSync(root, { recursive: true, force: true }); + } + }); +} diff --git a/scripts/dev-sync.sh b/scripts/dev-sync.sh index 750feb4f8..bb999cff1 100755 --- a/scripts/dev-sync.sh +++ b/scripts/dev-sync.sh @@ -21,6 +21,7 @@ CODEX_CACHE="${CODEX_CACHE:-$HOME/.codex/plugins/cache}" CLAUDE_CACHE="${CLAUDE_CACHE:-$HOME/.claude/plugins/cache}" CODEX_AGENTS="${CODEX_AGENTS:-$HOME/.codex/agents}" OPENCODE_SKILLS="${OPENCODE_SKILLS:-$HOME/.config/opencode/skills}" +OPENCODE_AGENTS="${OPENCODE_AGENTS:-$HOME/.config/opencode/agents}" HAVE_CODEX=0; command -v codex >/dev/null 2>&1 && HAVE_CODEX=1 HAVE_CLAUDE=0; command -v claude >/dev/null 2>&1 && HAVE_CLAUDE=1 @@ -36,6 +37,26 @@ build_tool() { --to "$tool" --out "$BUILD/$tool" --as "$mode" --force >/dev/null 2>&1 } +validate_opencode_content() { + local name agent skill skill_name + for name in "$@"; do + for skill in "$FW/plugins/$name/skills/"*/SKILL.md; do + skill_name="$(basename "$(dirname "$skill")")" + if [ ! -s "$BUILD/opencode/.opencode/skills/$name/$skill_name/SKILL.md" ] && + [ ! -s "$BUILD/opencode/.opencode/skills/$name-$skill_name/SKILL.md" ]; then + echo "no built OpenCode skill for $name-$skill_name (missing or empty SKILL.md)" >&2 + return 1 + fi + done + for agent in "$FW/plugins/$name/agents/"*.md; do + if [ ! -s "$BUILD/opencode/.opencode/agents/$name-$(basename "$agent")" ]; then + echo "no built OpenCode agent for $name-$(basename "$agent" .md)" >&2 + return 1 + fi + done + done +} + sync_opencode_skills() { local name source skill destination local -a skills @@ -43,10 +64,6 @@ sync_opencode_skills() { source="$BUILD/opencode/.opencode/skills" for name in "$@"; do skills=("$source/$name/"*/ "$source/$name-"*/) - if [ "${#skills[@]}" -eq 0 ]; then - echo "no built OpenCode skills for $name" >&2 - return 1 - fi rm -rf -- "$OPENCODE_SKILLS/$name" find "$OPENCODE_SKILLS" -mindepth 1 -maxdepth 1 -type d -name "$name-*" -exec rm -rf -- {} + for skill in "${skills[@]}"; do @@ -60,6 +77,18 @@ sync_opencode_skills() { done } +sync_opencode_agents() { + local name agent + mkdir -p "$OPENCODE_AGENTS" + for name in "$@"; do + # Only the selected plugin namespace is managed; personal and other plugins' agents stay. + for agent in "$OPENCODE_AGENTS/$name-"*.md; do rm -f -- "$agent"; done + for agent in "$BUILD/opencode/.opencode/agents/$name-"*.md; do + cp -f "$agent" "$OPENCODE_AGENTS/" + done + done +} + register_marketplace() { case "$1" in # Codex needs the built tree (the raw repo is Claude-syntax; Codex wants TOML/.codex-plugin). @@ -93,6 +122,8 @@ sync_one() { [ "$n" -gt 0 ] && printf '(+%d agents)' "$n" else printf ' codex:FAIL' + echo "Codex plugin install failed for $name; rerun codex plugin add $name@$MKT for details." >&2 + return 1 fi fi if [ "$HAVE_CLAUDE" = 1 ]; then @@ -114,10 +145,14 @@ sync_one() { [ "$fixed" -gt 0 ] && printf '(+%d agents, repaired %d)' "$n" "$fixed" || printf '(+%d agents)' "$n" else printf '(agents:NO-INSTALLPATH)' + echo "Claude plugin install path missing for $name; rerun claude plugin install $name@$MKT --scope user for details." >&2 + return 1 fi fi else printf ' claude:FAIL' + echo "Claude plugin install failed for $name; rerun claude plugin install $name@$MKT --scope user for details." >&2 + return 1 fi fi echo @@ -138,26 +173,30 @@ fi # repo (already native), so it only needs the marketplace registered - no build. if [ "$HAVE_CODEX" = 1 ]; then printf '%-22s' "build codex" - build_tool codex && { register_marketplace codex; echo "ok"; } || { echo "FAIL"; HAVE_CODEX=0; } + build_tool codex || { echo "FAIL"; echo "codex build failed; rerun the translate command in scripts/dev-sync.sh without output redirection for details." >&2; exit 1; } + register_marketplace codex || { echo "FAIL"; echo "Codex marketplace registration failed for $BUILD/codex." >&2; exit 1; } + echo "ok" fi if [ "$HAVE_CLAUDE" = 1 ]; then register_marketplace claude fi if [ "$HAVE_OPENCODE" = 1 ] && [ "$HAVE_MANAGED_OPENCODE" = 0 ]; then printf '%-22s' "build opencode" - build_tool opencode && echo "ok" || { echo "FAIL"; HAVE_OPENCODE=0; } + build_tool opencode && echo "ok" || { echo "FAIL"; echo "opencode build failed; rerun the translate command in scripts/dev-sync.sh without output redirection for details." >&2; exit 1; } fi for t in "${targets[@]}"; do sync_one "$t"; done if [ "$HAVE_OPENCODE" = 1 ] && [ "$HAVE_MANAGED_OPENCODE" = 0 ]; then printf '%-22s' "install opencode" + validate_opencode_content "${targets[@]}" sync_opencode_skills "${targets[@]}" - echo "skills:ok" + sync_opencode_agents "${targets[@]}" + echo "skills:ok agents:ok" fi if [ "$HAVE_MANAGED_OPENCODE" = 1 ]; then printf '%-22s' "reload opencode" aidd-opencode-reload fi -echo "Done. Restart Claude/Codex; OpenCode discovers the refreshed skills without a restart." +echo "Done. Restart Claude/Codex; reload OpenCode configuration for refreshed agents and skills." From 1cc3c0b2ea02f892bd7b533cea5311031afe2027 Mon Sep 17 00:00:00 2001 From: alexsoyes Date: Wed, 14 Oct 2026 14:02:10 +0800 Subject: [PATCH 05/73] test(framework): record native sub-agent verification Capture observed host invocations, scoped execution, parallel integration and the remaining controller and provider limits. Refs #983 --- .../2026_10_14_sub_agents/verification.md | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 aidd_docs/tasks/2026_10/2026_10_14_sub_agents/verification.md diff --git a/aidd_docs/tasks/2026_10/2026_10_14_sub_agents/verification.md b/aidd_docs/tasks/2026_10/2026_10_14_sub_agents/verification.md new file mode 100644 index 000000000..02c37dd52 --- /dev/null +++ b/aidd_docs/tasks/2026_10/2026_10_14_sub_agents/verification.md @@ -0,0 +1,51 @@ +# Sub-agent verification + +Verified 2026-10-14 on `feature/sub-agents`: workflow candidate `1f151d19`, delivery candidate `e00f124c`. + +## Native roles + +| Host | Version | Invoked roles | +| --- | --- | --- | +| Codex | 0.162.1 | explorer, executor, validator, checker | +| Claude Code | 2.1.299 | aidd-dev:explorer, aidd-dev:executor, aidd-dev:validator, aidd-dev:checker | +| OpenCode | 2.0.28 | aidd-dev-explorer, aidd-dev-executor, aidd-dev-validator, aidd-dev-checker | + +Native dispatch traces identify the selected roles and fresh child contexts. Agent self-reports alone were not used to establish invocation. + +| Scenario | Codex | Claude | OpenCode | +| --- | --- | --- | --- | +| Explorer cites the readiness rule and refuses a conflicting write request | PASS | PASS | PASS | +| Validator reports INCOMPLETE for the failing mandatory check without repair | PASS | PASS | PASS | +| Validator reports BLOCKED without criteria despite an offered green command | PASS | PASS | PASS | +| Executor invokes the installed implement skill for only its assigned phase | PASS | PASS | PASS | +| Fresh validator reports COMPLETE for the repaired, unchanged candidate | PASS | PASS | PASS | +| Checker reviews quality and fitness without modifying the candidate | PASS | PASS | PASS | + +Independent final readback found exact bytes `72 65 61 64 79 0a`, a passing `node check.cjs`, and only the assigned phase's lifecycle update. The shared plan, completed prerequisite, check command, and unrelated file retained their baseline contents. + +## Parallel implementation + +Two native Codex executors used separate supplied worktrees and Git indexes. Their recorded execution intervals overlapped by 19 seconds. Each invoked the installed assigned-phase workflow and committed only its own data file and phase status. + +| Phase | Executor commit | Integrated commit | Check | +| --- | --- | --- | --- | +| 1 | 551702df | 5e4bcaa1 | check-a.cjs: READY, exit 0 | +| 2 | add8b135 | 32521585 | check-b.cjs: READY, exit 0 | + +The caller integrated both, obtained `BOTH_READY` and exit 0 from `node check-all.cjs`, then committed plan status `implemented` at `c2b8ff32`. Independent readback confirmed the plan and both phases complete, with all three checkouts clean. These commits belong to the disposable probe repository, not the framework. + +A restricted-workspace negative probe could not write Git metadata. It reported BLOCKED and left the integrated plan incomplete. The successful disposable probe used the desktop's unrestricted execution profile. No authentication or product security control was changed. + +## Real-project planning + +The installed planning skill produced three phases in Gouvernail's `2026_10_14_sub_agents_plan_probe` folder: two disjoint diagnostic scripts with no prerequisites, followed by shared package-command wiring depending on both. The phase projections and dependency table were inspected. No application source changed. Session-start memory formatting changes were restored; only the probe artifacts remain. + +The large-project planning and review controllers exceeded their imposed time limits after producing the artifacts. Their full interactive completion is not claimed. Codex's combined role controller also exceeded its limit; its native thread subsequently emitted all six results and `turn.completed`. A separate normal-session validator probe exited 0. + +## Delivery and gates + +`make reload` ran without `PLUGIN`, installing all nine plugins. OpenCode skills and agents were compared with the generated tree; native discovery listed all four roles. Claude's manifest explicitly declares the new agents. + +OpenCode's configured local model server was unavailable. Its behavioral probe used the already authenticated `openai/gpt-6.1-sol` through an invocation-only override, with matching `cwd` and `PWD`. Global model and authentication settings were unchanged. Versioned discovery and directory behavior sources are recorded in deployment memory. + +The wrapped scripts suite passed 559 tests, including 12 reload regressions. Architecture, JSON manifest validation, Markdown links, duplication checks, and commit hooks passed. These results establish the observed contracts and host paths; they do not guarantee every future task or model choice. From 77094596b196ed9617c1abc104872a118c245be5 Mon Sep 17 00:00:00 2001 From: alexsoyes Date: Wed, 14 Oct 2026 15:59:10 +0800 Subject: [PATCH 06/73] fix(framework): reload global instructions across hosts --- aidd_docs/memory/deployment.md | 13 +++ scripts/__tests__/dev-sync.test.js | 155 ++++++++++++++++++++++++++- scripts/dev-sync.sh | 18 +++- scripts/sync-global-instructions.cjs | 61 +++++++++++ 4 files changed, 244 insertions(+), 3 deletions(-) create mode 100644 scripts/sync-global-instructions.cjs diff --git a/aidd_docs/memory/deployment.md b/aidd_docs/memory/deployment.md index cd8af01d2..38f686a0f 100644 --- a/aidd_docs/memory/deployment.md +++ b/aidd_docs/memory/deployment.md @@ -63,6 +63,19 @@ namespaced agents into the global directories, replacing only selected plugin na Missing expected build files fail before changing installed OpenCode content. A managed OpenCode host keeps its fixed-purpose `aidd-opencode-reload` helper. +Reload also updates a managed AIDD block in each installed host's global instructions: +Codex `~/.codex/AGENTS.md`, Claude `~/.claude/CLAUDE.md`, OpenCode +`~/.config/opencode/AGENTS.md`. Personal text remains outside the block. The framework's +entire Memory Management section and its local architecture-file obligation are excluded; +agent names match the host. First OpenCode sync preserves its previous Claude personal-rule +fallback. `CODEX_HOME`, `CLAUDE_CONFIG_DIR`, and `XDG_CONFIG_HOME` relocate instruction +destinations; explicit `*_INSTRUCTIONS` overrides are available to isolate tests. + +Global instruction locations and OpenCode fallback precedence checked 2026-10-14: +[Codex](https://developers.openai.com/codex/guides/agents-md), +[Claude](https://code.claude.com/docs/en/memory), +[OpenCode](https://opencode.ai/docs/rules/). + OpenCode V2 documents global agents at `~/.config/opencode/agents/`, filename-based agent names, and `mode: subagent`. Native restrictions use a `permissions` list with `action`, `resource`, and `effect`; `edit` covers write, edit and patch, `shell` gates commands, and diff --git a/scripts/__tests__/dev-sync.test.js b/scripts/__tests__/dev-sync.test.js index 2c0fcf9ba..50f9200af 100644 --- a/scripts/__tests__/dev-sync.test.js +++ b/scripts/__tests__/dev-sync.test.js @@ -2,13 +2,94 @@ const assert = require("node:assert/strict"); const { spawnSync } = require("node:child_process"); const { chmodSync, existsSync, mkdtempSync, mkdirSync, readFileSync, rmSync, writeFileSync } = require("node:fs"); const { tmpdir } = require("node:os"); -const { delimiter, join, resolve } = require("node:path"); +const { delimiter, dirname, join, resolve } = require("node:path"); const test = require("node:test"); const repo = resolve(__dirname, "../.."); +const { render, sync } = require("../sync-global-instructions.cjs"); const devAgents = ["checker.md", "executor.md"]; const buildDevAgents = devAgents.map((name) => `printf '%s\\n' 'updated agent' > "$out/.opencode/agents/aidd-dev-${name}"`).join("\n"); +const instructionSource = "# AGENTS.md\n\n## Action\n- Keep scope.\n- Follow `docs/ARCHITECTURE.md`.\n\n## Agents\n| name | role |\n| --- | --- |\n| @executor (Codex), @aidd-dev-executor (OpenCode) | Implement scope. |\n\n## Memory Management\nProject docs live in aidd_docs/.\n\n@aidd_docs/memory/private.md\n\nLoad more memory.\n"; + +test("global instructions exclude project context and use each host's native agent names", () => { + for (const [host, name] of [["codex", "@executor"], ["claude", "@aidd-dev:executor"], ["opencode", "@aidd-dev-executor"]]) { + const content = render(instructionSource, host); + assert.ok(content.includes(`| ${name} | Implement scope. |`)); + assert.doesNotMatch(content, /Memory|memory|aidd_docs|ARCHITECTURE/); + assert.match(content, /Keep scope/); + } +}); + +test("global sync preserves personal rules, updates its block, and is idempotent", () => { + const root = mkdtempSync(join(tmpdir(), "aidd-global-rules-")); + try { + const source = join(root, "source.md"); + const destination = join(root, "codex/AGENTS.md"); + mkdirSync(dirname(destination), { recursive: true }); + writeFileSync(source, instructionSource); + const personal = "Personal rules with no trailing newline"; + writeFileSync(destination, personal); + sync(source, [["codex", destination]]); + const first = readFileSync(destination, "utf8"); + sync(source, [["codex", destination]]); + assert.equal(readFileSync(destination, "utf8"), first); + writeFileSync(source, instructionSource.replace("Keep scope.", "Check scope.")); + sync(source, [["codex", destination]]); + const updated = readFileSync(destination, "utf8"); + assert.ok(updated.startsWith(personal)); + assert.match(updated, /Check scope/); + assert.doesNotMatch(updated, /Keep scope/); + assert.equal(updated.split("aidd_global_instructions:start").length, 2); + } finally { + rmSync(root, { recursive: true, force: true }); + } +}); + +test("first OpenCode sync retains effective Claude personal rules without its managed block", () => { + const root = mkdtempSync(join(tmpdir(), "aidd-global-fallback-")); + try { + const source = join(root, "source.md"); + const claude = join(root, "CLAUDE.md"); + const opencode = join(root, "opencode/AGENTS.md"); + writeFileSync(source, instructionSource); + writeFileSync(claude, "Claude personal rules.\n"); + sync(source, [["claude", claude]]); + sync(source, [["opencode", opencode]], claude); + const installed = readFileSync(opencode, "utf8"); + assert.match(installed, /Claude personal rules/); + assert.match(installed, /@aidd-dev-executor/); + assert.doesNotMatch(installed, /@aidd-dev:executor/); + writeFileSync(claude, "Changed fallback.\n"); + sync(source, [["opencode", opencode]], claude); + assert.equal(readFileSync(opencode, "utf8"), installed); + } finally { + rmSync(root, { recursive: true, force: true }); + } +}); + +test("malformed managed blocks and missing memory boundaries leave all global files untouched", () => { + const root = mkdtempSync(join(tmpdir(), "aidd-global-invalid-")); + try { + const source = join(root, "source.md"); + const codex = join(root, "AGENTS.md"); + const claude = join(root, "CLAUDE.md"); + writeFileSync(source, instructionSource); + writeFileSync(codex, "Keep Codex.\n"); + for (const malformed of ["", "", "".repeat(2)]) { + writeFileSync(claude, malformed); + assert.throws(() => sync(source, [["codex", codex], ["claude", claude]]), /Malformed/); + assert.equal(readFileSync(codex, "utf8"), "Keep Codex.\n"); + assert.equal(readFileSync(claude, "utf8"), malformed); + } + writeFileSync(source, "Unbounded context.\n"); + assert.throws(() => sync(source, [["codex", codex]]), /Memory Management boundary/); + assert.equal(readFileSync(codex, "utf8"), "Keep Codex.\n"); + } finally { + rmSync(root, { recursive: true, force: true }); + } +}); + function executable(path, body) { writeFileSync(path, `#!/bin/sh\nset -eu\n${body}\n`); chmodSync(path, 0o755); @@ -28,6 +109,7 @@ function fixture(home) { writeFileSync(join(pluginDir, "agents", name), "source agent\n"); } } + writeFileSync(join(source, "AGENTS.md"), "# AGENTS.md\n\n## Behavior\nKeep scope.\n\n## Memory Management\nProject-only memory.\n"); } return source; } @@ -39,7 +121,8 @@ function fixture(home) { const BASE_PATH = process.platform === "win32" ? (process.env.PATH ?? "") : ["/usr/bin", "/bin"].join(delimiter); -function runSync(fakeBin, home, args = ["all"]) { +function runSync(fakeBin, home, args = ["all"], overrides = {}) { + executable(join(fakeBin, "node"), `exec '${process.execPath}' "$@"`); // `bash`, resolved on PATH, never the literal `/bin/bash`: that path does not exist on // Windows, where bash is the one Git for Windows ships. `spawnSync` resolves a bare name // through the platform's own rules on both. @@ -56,6 +139,12 @@ function runSync(fakeBin, home, args = ["all"]) { CODEX_AGENTS: join(home, ".codex/agents"), OPENCODE_SKILLS: join(home, ".config/opencode/skills"), OPENCODE_AGENTS: join(home, ".config/opencode/agents"), + CODEX_INSTRUCTIONS: join(home, ".codex/AGENTS.md"), + CLAUDE_INSTRUCTIONS: join(home, ".claude/CLAUDE.md"), + OPENCODE_INSTRUCTIONS: join(home, ".config/opencode/AGENTS.md"), + OPENCODE_DISABLE_CLAUDE_CODE: "", + OPENCODE_DISABLE_CLAUDE_CODE_PROMPT: "", + ...overrides, }, encoding: "utf8", }); @@ -74,6 +163,68 @@ test("managed OpenCode reload uses the fixed-purpose helper without a local buil assert.equal(result.status, 0, result.stderr); assert.match(result.stdout, /reload opencode\s+managed:ok/); assert.equal(existsSync(join(home, "build")), false); + assert.match(readFileSync(join(home, ".config/opencode/AGENTS.md"), "utf8"), /Keep scope/); + } finally { + rmSync(root, { recursive: true, force: true }); + } +}); + +for (const flag of ["OPENCODE_DISABLE_CLAUDE_CODE", "OPENCODE_DISABLE_CLAUDE_CODE_PROMPT"]) { + test(`OpenCode first reload respects disabled Claude fallback via ${flag}`, () => { + const root = mkdtempSync(join(tmpdir(), "aidd-dev-sync-no-fallback-")); + try { + const fakeBin = join(root, "bin"); + const home = join(root, "home"); + mkdirSync(fakeBin); + mkdirSync(join(home, ".claude"), { recursive: true }); + writeFileSync(join(home, ".claude/CLAUDE.md"), "Excluded Claude personal rules.\n"); + executable(join(fakeBin, "aidd-opencode-reload"), "exit 0"); + const result = runSync(fakeBin, home, [], { [flag]: "1" }); + assert.equal(result.status, 0, result.stderr); + const installed = readFileSync(join(home, ".config/opencode/AGENTS.md"), "utf8"); + assert.doesNotMatch(installed, /Excluded Claude/); + assert.match(installed, /Keep scope/); + } finally { + rmSync(root, { recursive: true, force: true }); + } + }); +} + +test("reload delivers global instructions to all three hosts while preserving personal rules", () => { + const root = mkdtempSync(join(tmpdir(), "aidd-dev-sync-rules-")); + try { + const fakeBin = join(root, "bin"); + const home = join(root, "home"); + mkdirSync(fakeBin); + mkdirSync(home); + const source = fixture(home); + writeFileSync(join(source, "AGENTS.md"), instructionSource); + const destinations = [[".codex/AGENTS.md", "@executor"], [".claude/CLAUDE.md", "@aidd-dev:executor"], [".config/opencode/AGENTS.md", "@aidd-dev-executor"]]; + for (const [path] of destinations) { + mkdirSync(dirname(join(home, path)), { recursive: true }); + writeFileSync(join(home, path), "Personal rules.\n"); + } + for (const host of ["codex", "claude", "opencode"]) executable(join(fakeBin, host), "exit 0"); + executable(join(fakeBin, "npx"), String.raw`out="" +while [ "$#" -gt 0 ]; do + if [ "$1" = "--out" ]; then shift; out=$1; fi + shift +done +mkdir -p "$out/.opencode/skills/aidd-pm-03-prd" +printf '%s\n' 'skill' > "$out/.opencode/skills/aidd-pm-03-prd/SKILL.md"`); + const first = runSync(fakeBin, home, ["aidd-pm"]); + assert.equal(first.status, 0, first.stderr); + assert.match(first.stdout, /global instructions\s+ok/); + const contents = destinations.map(([path, name]) => { + const content = readFileSync(join(home, path), "utf8"); + assert.ok(content.startsWith("Personal rules.\n")); + assert.ok(content.includes(`| ${name} | Implement scope. |`)); + assert.doesNotMatch(content, /Memory|aidd_docs|ARCHITECTURE/); + return content; + }); + const second = runSync(fakeBin, home, ["aidd-pm"]); + assert.equal(second.status, 0, second.stderr); + destinations.forEach(([path], index) => assert.equal(readFileSync(join(home, path), "utf8"), contents[index])); } finally { rmSync(root, { recursive: true, force: true }); } diff --git a/scripts/dev-sync.sh b/scripts/dev-sync.sh index bb999cff1..21db8d3ee 100755 --- a/scripts/dev-sync.sh +++ b/scripts/dev-sync.sh @@ -22,6 +22,9 @@ CLAUDE_CACHE="${CLAUDE_CACHE:-$HOME/.claude/plugins/cache}" CODEX_AGENTS="${CODEX_AGENTS:-$HOME/.codex/agents}" OPENCODE_SKILLS="${OPENCODE_SKILLS:-$HOME/.config/opencode/skills}" OPENCODE_AGENTS="${OPENCODE_AGENTS:-$HOME/.config/opencode/agents}" +CODEX_INSTRUCTIONS="${CODEX_INSTRUCTIONS:-${CODEX_HOME:-$HOME/.codex}/AGENTS.md}" +CLAUDE_INSTRUCTIONS="${CLAUDE_INSTRUCTIONS:-${CLAUDE_CONFIG_DIR:-$HOME/.claude}/CLAUDE.md}" +OPENCODE_INSTRUCTIONS="${OPENCODE_INSTRUCTIONS:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode/AGENTS.md}" HAVE_CODEX=0; command -v codex >/dev/null 2>&1 && HAVE_CODEX=1 HAVE_CLAUDE=0; command -v claude >/dev/null 2>&1 && HAVE_CLAUDE=1 @@ -199,4 +202,17 @@ if [ "$HAVE_MANAGED_OPENCODE" = 1 ]; then aidd-opencode-reload fi -echo "Done. Restart Claude/Codex; reload OpenCode configuration for refreshed agents and skills." +instructions=() +[ "$HAVE_CODEX" = 0 ] || instructions+=(codex "$CODEX_INSTRUCTIONS") +[ "$HAVE_CLAUDE" = 0 ] || instructions+=(claude "$CLAUDE_INSTRUCTIONS") +if [ "$HAVE_OPENCODE" = 1 ] || [ "$HAVE_MANAGED_OPENCODE" = 1 ]; then + instructions+=(opencode "$OPENCODE_INSTRUCTIONS") +fi +printf '%-22s' "global instructions" +instruction_fallback="$CLAUDE_INSTRUCTIONS" +case "${OPENCODE_DISABLE_CLAUDE_CODE:-}" in 1|true) instruction_fallback="" ;; esac +case "${OPENCODE_DISABLE_CLAUDE_CODE_PROMPT:-}" in 1|true) instruction_fallback="" ;; esac +node "$SCRIPT_DIR/sync-global-instructions.cjs" "$FW/AGENTS.md" "$instruction_fallback" "${instructions[@]}" +echo "ok (project memory excluded)" + +echo "Done. Restart Claude/Codex; reload OpenCode configuration for refreshed agents, skills, and instructions." diff --git a/scripts/sync-global-instructions.cjs b/scripts/sync-global-instructions.cjs new file mode 100644 index 000000000..3e02feb40 --- /dev/null +++ b/scripts/sync-global-instructions.cjs @@ -0,0 +1,61 @@ +const { existsSync, mkdirSync, readFileSync, writeFileSync } = require("node:fs"); +const { dirname } = require("node:path"); + +const start = ""; +const end = ""; + +function render(source, host) { + const boundary = source.search(/^## Memory Management\s*$/m); + if (boundary < 0) throw new Error("AGENTS.md has no Memory Management boundary; refusing global sync"); + const names = { + codex: (role) => `@${role}`, + claude: (role) => `@aidd-dev:${role}`, + opencode: (role) => `@aidd-dev-${role}`, + }; + if (!names[host]) throw new Error(`Unknown instruction host: ${host}`); + return source.slice(0, boundary).trim().replace(/^.*\bdocs\/ARCHITECTURE\.md.*\n?/gm, "").replace( + /^\| @([a-z]+)[^|]*\|/gm, + (_, role) => `| ${names[host](role)} |`, + ); +} + +function merge(existing, content) { + const starts = existing.split(start).length - 1; + const ends = existing.split(end).length - 1; + if (starts !== ends || starts > 1 || (starts === 1 && existing.indexOf(start) > existing.indexOf(end))) { + throw new Error("Malformed global AIDD instruction block; refusing to overwrite personal rules"); + } + const block = content === null ? "" : `${start}\n${content}\n${end}`; + if (starts === 1) { + return existing.slice(0, existing.indexOf(start)) + block + existing.slice(existing.indexOf(end) + end.length); + } + if (content === null) return existing; + return existing + (existing.endsWith("\n\n") || !existing ? "" : existing.endsWith("\n") ? "\n" : "\n\n") + block + "\n"; +} + +function sync(sourcePath, destinations, claudeFallback) { + const source = readFileSync(sourcePath, "utf8"); + // Prepare every destination before writing any: a malformed block must not partially sync hosts. + const updates = destinations.map(([host, path]) => { + let existing = existsSync(path) ? readFileSync(path, "utf8") : ""; + // Creating OpenCode's global file disables its Claude fallback. Keep those personal rules. + if (host === "opencode" && !existsSync(path) && claudeFallback && existsSync(claudeFallback)) { + existing = merge(readFileSync(claudeFallback, "utf8"), null); + } + return { path, content: merge(existing, render(source, host)) }; + }); + for (const { path, content } of updates) { + mkdirSync(dirname(path), { recursive: true }); + writeFileSync(path, content); + } +} + +module.exports = { render, merge, sync }; + +if (require.main === module) { + const [sourcePath, claudeFallback, ...args] = process.argv.slice(2); + if (!sourcePath || claudeFallback === undefined || args.length % 2) throw new Error("Usage: sync-global-instructions.cjs SOURCE CLAUDE_FALLBACK [HOST DESTINATION ...]"); + const destinations = []; + for (let i = 0; i < args.length; i += 2) destinations.push([args[i], args[i + 1]]); + sync(sourcePath, destinations, claudeFallback); +} From dbf82b757743ec253df6a72084925cbcbc94eaac Mon Sep 17 00:00:00 2001 From: alexsoyes Date: Wed, 14 Oct 2026 16:24:28 +0800 Subject: [PATCH 07/73] refactor(aidd-dev): trim workflows and template agent outputs --- aidd_docs/memory/deployment.md | 32 +--------- docs/ARCHITECTURE.md | 10 ++-- .../02-project-memory/actions/04-sync.md | 34 ++++------- plugins/aidd-dev/agents/checker.md | 50 ++++++++-------- plugins/aidd-dev/agents/executor.md | 48 +++++++++------ plugins/aidd-dev/agents/explorer.md | 28 +++++---- plugins/aidd-dev/agents/validator.md | 34 ++++++----- plugins/aidd-dev/skills/01-plan/SKILL.md | 38 ++++-------- .../skills/01-plan/actions/01-gather.md | 17 +++--- .../skills/01-plan/actions/02-explore.md | 29 ++++----- .../skills/01-plan/actions/03-wireframe.md | 16 ++--- .../skills/01-plan/actions/04-plan.md | 59 +++++++------------ .../skills/01-plan/references/plan-status.md | 8 +-- .../references/wireframe-conventions.md | 8 +-- plugins/aidd-dev/skills/02-implement/SKILL.md | 35 +++++------ .../skills/02-implement/actions/01-prepare.md | 21 +++---- .../skills/02-implement/actions/02-execute.md | 46 +++++---------- .../02-implement/actions/03-finalize.md | 25 +++----- .../skills/01-sdlc/references/02-deliver.md | 11 ++-- .../skills/01-sdlc/references/03-check.md | 9 ++- scripts/dev-sync.sh | 15 +++++ 21 files changed, 237 insertions(+), 336 deletions(-) diff --git a/aidd_docs/memory/deployment.md b/aidd_docs/memory/deployment.md index 38f686a0f..ff79cff50 100644 --- a/aidd_docs/memory/deployment.md +++ b/aidd_docs/memory/deployment.md @@ -58,37 +58,7 @@ Config: `release-please-config.json`, eleven packages. Manifest: `.release-pleas ## Local reload -`make reload` refreshes every plugin. `scripts/dev-sync.sh` copies built OpenCode skills and -namespaced agents into the global directories, replacing only selected plugin namespaces. -Missing expected build files fail before changing installed OpenCode content. A managed -OpenCode host keeps its fixed-purpose `aidd-opencode-reload` helper. - -Reload also updates a managed AIDD block in each installed host's global instructions: -Codex `~/.codex/AGENTS.md`, Claude `~/.claude/CLAUDE.md`, OpenCode -`~/.config/opencode/AGENTS.md`. Personal text remains outside the block. The framework's -entire Memory Management section and its local architecture-file obligation are excluded; -agent names match the host. First OpenCode sync preserves its previous Claude personal-rule -fallback. `CODEX_HOME`, `CLAUDE_CONFIG_DIR`, and `XDG_CONFIG_HOME` relocate instruction -destinations; explicit `*_INSTRUCTIONS` overrides are available to isolate tests. - -Global instruction locations and OpenCode fallback precedence checked 2026-10-14: -[Codex](https://developers.openai.com/codex/guides/agents-md), -[Claude](https://code.claude.com/docs/en/memory), -[OpenCode](https://opencode.ai/docs/rules/). - -OpenCode V2 documents global agents at `~/.config/opencode/agents/`, filename-based agent -names, and `mode: subagent`. Native restrictions use a `permissions` list with `action`, -`resource`, and `effect`; `edit` covers write, edit and patch, `shell` gates commands, and -`subagent` gates delegation. Source: , read 2026-10-14. -V2.0.28 also migrates legacy Markdown fields during discovery: -, -read 2026-10-14. After reload, `opencode debug agents` lists installed names; file presence -alone does not establish discovery, invocation, or permission enforcement. - -For an OpenCode V2.0.28 subprocess probe, set both its working directory and `PWD` to the -fixture: `run` prefers `process.env.PWD` over `process.cwd()` and changes directory to it. -Source: , -read 2026-10-14. +`make reload` syncs all plugins and global instructions to Claude, Codex, and OpenCode; details in `scripts/dev-sync.sh`. ## Monitoring diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 9db584b29..79382ce34 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -136,7 +136,7 @@ flowchart LR ActionN --> Out ``` -Recipe skills route to self-contained actions with inputs, outputs, process steps, and tests. An orchestrator with no domain logic may instead route through numbered reference protocols that define handoffs and delegate the work to capabilities discovered at runtime. +Recipe skills route to self-contained actions with inputs, outputs, process steps, and rules. An orchestrator with no domain logic may instead route through numbered reference protocols that define handoffs and delegate the work to capabilities discovered at runtime. A skill never links outside itself (`scripts/__tests__/a-skill-links-only-inside-itself.test.js`). The same tree ships flat, where the skill folder is renamed `-`, or as a marketplace, so no relative path survives both. A bundled script is named plugin-relative in backticks, never linked. @@ -147,16 +147,14 @@ A skill never links outside itself (`scripts/__tests__/a-skill-links-only-inside Choose by context, not complexity: keep the work visible to the caller → skill; isolate it and take only the result → agent. -- **The primary caller owns delegation.** A user-invoked recipe may offer bounded delegation through available host capabilities. An orchestrator owns delegation when it invokes the recipe. Neither requires a fixed provider or model. -- A primary caller may delegate independent read-only questions to explorers and independent implementation phases to executors. It owns scope, dependencies, shared state, integration, and acceptance. Concurrent writers need distinct checkouts and nonconflicting validation resources; otherwise execution stays serial. -- An isolated agent is a leaf. It never spawns another agent or invokes an orchestrator. It invokes only recipe skills listed under `# Skills you may invoke`, using their canonical `/plugin:folder` addresses without reading their files. -- Independent validation uses a validator on an identified candidate. A checker reviews quality and outcome using that evidence. Neither modifies the candidate; gaps return to the primary caller for repair and renewed verification. +- **Caller:** own delegation, integration, and acceptance; use available agents when useful. +- **Agent:** stay within assigned scope, never delegate or invoke an orchestrator, and invoke only declared recipe skills without reading their files. ## 🔗 Capability addressing Address a capability only where the dispatch is declared: a router's `## Actions` table, an agent's `# Skills you may invoke` list. Everywhere else, name the concept the capability owns, never the skill that owns it. -Recipe skills never hardcode a sibling provider. They discover cross-plugin capabilities at runtime through description matching. Agent permission lists name allowed skills with canonical `/plugin:folder` addresses. Orchestration references map responsibilities to providers discovered from installed descriptions; canonical addresses in diagrams illustrate current providers. Verify availability and the role contract before dispatch. +Recipe skills discover providers by description. Agent allowlists use canonical `/plugin:folder` addresses; orchestration diagrams illustrate providers. Verify availability and role before dispatch. Two paths are exempt, both in `isExemptFromOrthogonality`: diff --git a/plugins/aidd-context/skills/02-project-memory/actions/04-sync.md b/plugins/aidd-context/skills/02-project-memory/actions/04-sync.md index 9fa1dd693..e7cd958e7 100644 --- a/plugins/aidd-context/skills/02-project-memory/actions/04-sync.md +++ b/plugins/aidd-context/skills/02-project-memory/actions/04-sync.md @@ -16,27 +16,15 @@ Each picked tool's context file, carrying the memory block and available agent t 2. **Detect.** Find the AI tools present per [tools.md](../references/tools.md). 3. **Pick.** Show every tool, the detected ones ticked, and wait for one or several. 4. **Upsert.** Ensure each picked tool's context file carries the block, per [tools.md](../references/tools.md). - - Absent file: create it from [AGENTS.md](../assets/templates/AGENTS.md). - - Its AIDD structure differs: offer to reconcile it, applying only what the user approves. + - **Absent:** create it from [AGENTS.md](../assets/templates/AGENTS.md). + - **Different:** reconcile its AIDD structure only with approval. 5. **Fill.** Run `hooks/update_memory.js` from the project root, naming the picked tools, and stop on a non-zero exit. - - No script, the skill shipped alone: write each block from the bank. -6. **Agents.** Inspect the picked tools' available agent definitions and registration. Fill or replace only `aidd_agents:start` / `aidd_agents:end` with a `name | role` table. - - List only installed, invocable agents. Use their actual host identities, including plugin namespaces or flat prefixes; never assume a short role name is callable everywhere. - - Write short English descriptions beginning with the role's action verb. Keep detailed contracts in the agent definitions. - - When tools share a context file, label differing identities by host. Omit unavailable roles; leave only the table header if no agents are available. - - Preserve all user text outside the managed markers. Add the block when absent; do not add a discovery script or session hook. -7. **Verify.** Read each picked tool's block back and compare it to the bank. - - A file in one and not the other: the fill did not land, report it and stop. - -## Test - -| Case | Pass | -| --- | --- | -| Empty bank | no context file created, the run stops | -| Script | it exits `0` | -| Picked tool | its block lists every root `.md` except `README.md`, nothing else | -| Bank grew | the block gains that file and keeps the rest | -| Unpicked tool | its context file is unchanged | -| Agent table | every row resolves to an installed agent on its labelled host | -| Agent unavailable | no row advertises it | -| Existing context | text outside managed blocks is preserved | + - **Standalone:** without the script, fill each block from the bank. +6. **Agents.** Fill `aidd_agents:start` / `aidd_agents:end` with installed, invocable agents and short English verb-led roles; label differing names by host in shared files. +7. **Verify.** Read back each selected block; stop if it differs from the bank or advertises an unavailable agent. + +## Rules + +- **Memory:** list every root `.md` except `README.md`. +- **Preserve:** leave unselected tools and text outside managed blocks unchanged. +- **Missing block:** add the agent block, even if only its table header; no new discovery hook or script. diff --git a/plugins/aidd-dev/agents/checker.md b/plugins/aidd-dev/agents/checker.md index 62aea7815..77e4c742d 100644 --- a/plugins/aidd-dev/agents/checker.md +++ b/plugins/aidd-dev/agents/checker.md @@ -5,41 +5,37 @@ description: Reviews quality, risks, and fitness for the intended need. Use for # Role -Review the deliverable's quality, risks, and fitness for its intended need in a fresh context. +Review quality, risks, and fitness for the intended need in a fresh context. # Behavior -- Read the intended need, acceptance criteria, candidate identity, and available validation evidence. Extend the checklist below with the project's own review checklist when it provides one. -- Use existing completion evidence. Repeat targeted checks only when it is insufficient, inconsistent, or stale; report missing validation instead of duplicating the full completion suite. -- Run the checklist on every code or diff, leaving no item unchecked. -- Then check the layer the reviews miss: does the delivered logic serve the actual need, end to end, even when code review and functional review both pass? Name any gap between intent and result. -- Demand command output or file evidence, never bare claims. Report concrete risks with their impact and uncertainty. -- When a review skill fits the work, run it and let it write its report; that report is your deliverable and your judgment is what fills it. Never hand-write a parallel prose review beside it. -- Return your verdict, findings, and score on top. Hold yourself accountable for whatever you pass. +- **Ground.** Read the need, criteria, candidate identity, and validation evidence; flag ambiguity instead of guessing. +- **Inspect.** Apply the project's checklist; check duplication, contradictions, unnecessary complexity, leftovers, and gaps between intent and result. +- **Verify.** Reuse validation evidence; repeat targeted checks only when insufficient, inconsistent, or stale. +- **Report.** Tie findings to evidence and impact; use supplied checklist thresholds without inventing a score. +- **Reuse.** When a review skill fits, let its report carry findings; reference it below instead of writing a duplicate. +- **Read only.** Never edit the deliverable or its validator, implement fixes, or delegate. -# Checklist +# Output -This is the behavioral baseline. Apply it to every code or diff, and extend it with the project's own checklist when one exists. +Fill this Markdown template; replace placeholders and use `None` for empty fields. +Use the findings table only when no skill report carries those findings. -- [ ] No information duplication. DRY across code and docs; link to the canonical home instead of copying. -- [ ] No incoherence or contradiction. Naming, behavior, and docs-versus-code stay consistent. -- [ ] No over-engineering. The simplest solution that meets the need; no speculative generality, no unused abstraction. -- [ ] No dead code or debug leftovers. No commented-out blocks, stray logs, or silent TODOs. +```markdown +## Review: -# Scoring +- **Candidate:** +- **Verdict:** +- **Report:** +- **Blockers:** -- If the supplied review checklist defines weights and thresholds, apply them exactly, and let any hard violation force the score to zero. -- Otherwise score quality and fitness for the need against the review checklist, adjusted for finding severity, with your reasoning. -- The pass threshold is the caller's gate, not yours. You report the score; you do not declare pass or fail. - -# Guardrails - -- Never edit the work or its validator. Never implement the fix. Never delegate to another agent. -- Never pass on vibes: tie every verdict to a stated criterion, a checklist item, or a named need-gap. -- Flag an ambiguous criterion instead of guessing. Do not go easy because the work looks impressive. +| Finding | Impact | Evidence | Suggested action | +| --- | --- | --- | --- | +| | | | | +``` # Skills you may invoke -- `/aidd-dev:05-review` -- `/aidd-dev:04-audit` -- `/aidd-refine:02-challenge` +- **Review.** `/aidd-dev:05-review` +- **Audit.** `/aidd-dev:04-audit` +- **Challenge.** `/aidd-refine:02-challenge` diff --git a/plugins/aidd-dev/agents/executor.md b/plugins/aidd-dev/agents/executor.md index f7244af59..9116bc968 100644 --- a/plugins/aidd-dev/agents/executor.md +++ b/plugins/aidd-dev/agents/executor.md @@ -5,30 +5,40 @@ description: Turns a dispatched task into working, validated code that fits the # Role -You are the executor. Your job is to turn a dispatched task into working, validated code that fits the project. You decide how, never what. +Implement the assigned scope. Decide how, never what. # Behavior -- Honour the project's own conventions where it defines them, and match the code around you. Where it stays silent, follow the prevailing idiom. -- Internalize the acceptance criteria before writing anything. If the scope is ambiguous, surface it instead of guessing. -- Work in a tight loop: build a substep, validate it, repair on red, and only then move on. Validation passing is the gate, never your own say-so. -- When a validation failure has no clear cause, run `/aidd-dev:08-debug` before repairing and validating again. -- In an assigned phase, execute only that phase. Return checks and changes to the caller before unrelated phases begin. -- Commit only when authorized and when you own the Git index. In parallel work, leave shared Git operations and plan updates to the caller. -- When you finish or stall, return to whoever invoked you with what is done, what is left, and why. +- **Scope.** Follow acceptance criteria and project conventions; stop on ambiguity or drift. +- **Build.** Validate each substep, repair failures, and repeat; debug an unclear cause first. +- **Complete.** Report COMPLETE only after assigned criteria and mandatory checks pass. +- **Ownership.** Change only assigned files and lifecycle status; an assigned phase never updates shared-plan status. +- **Git.** Commit only when authorized and owning the Git index; leave shared operations to the caller. +- **Report.** Return changes, checks, remaining work, and blockers; disclose skipped checks or placeholders. +- **Boundary.** Never change requirements, review your own work, or delegate; stop at inaccessible human actions. -# Guardrails +# Output -- Never change plan content, scope, specs, or acceptance criteria. Update lifecycle status only for plan or phase files assigned by the caller. An assigned-phase executor never updates shared-plan status. On drift, stop and hand it back to be replanned. -- Stay strictly in the scope you are handed. Declare anything you bypass: no silent TODO, skipped test, or placeholder mock. -- Never judge your own work, and never start a review. The caller handles that. -- Never delegate to another agent. -- When the work is physically impossible for the AI, stop and say so plainly: a real payment, a human login, an unreadable secret, anything behind hardware or 2FA. Do not fake progress. +Fill this Markdown template; replace placeholders and use `None` for empty fields. + +```markdown +## Implementation: + +- **Status:** +- **Candidate:** +- **Changes:** +- **Remaining:** +- **Blockers:** + +| Check | Result | Evidence | +| --- | --- | --- | +| | | | +``` # Skills you may invoke -- `/aidd-dev:02-implement` -- `/aidd-dev:03-assert` -- `/aidd-dev:06-test` -- `/aidd-dev:08-debug` -- `/aidd-vcs:01-commit` +- **Implement.** `/aidd-dev:02-implement` +- **Assert.** `/aidd-dev:03-assert` +- **Test.** `/aidd-dev:06-test` +- **Debug.** `/aidd-dev:08-debug` +- **Commit.** `/aidd-vcs:01-commit` diff --git a/plugins/aidd-dev/agents/explorer.md b/plugins/aidd-dev/agents/explorer.md index 1d6bf5c4c..15d06d93e 100644 --- a/plugins/aidd-dev/agents/explorer.md +++ b/plugins/aidd-dev/agents/explorer.md @@ -5,20 +5,28 @@ description: Explores scoped questions and returns sourced findings. Use when a # Role -Explore the assigned question. Return evidence to the caller without deciding implementation scope. +Explore an assigned question or codebase domain for the caller's decision. # Behavior -- Read relevant code, documentation, and sources. Trace relationships needed to answer the question. -- Separate observed facts from inference. Cite file paths and lines or source URLs. -- Report uncertainties, conflicting evidence, and material risks. -- Stay within the question. Return unresolved questions instead of expanding the task. +- **Trace.** Read relevant code and sources, including relationships across the assigned domain's boundary. +- **Ground.** Separate observations from inference; cite file lines or source URLs. +- **Bound.** Report uncertainty and risks without expanding scope or deciding implementation. +- **Read only.** Never mutate inspected material, implement, delegate, or invoke an orchestrator. -# Outputs +# Output -Return a concise answer, verifiable references, and remaining uncertainties. +Fill this Markdown template; replace placeholders and use `None` for empty fields. -# Guardrails +```markdown +## Exploration: -- Never modify files or external state. Do not run commands that mutate the inspected material. -- Never implement changes, delegate work, or invoke an orchestrator. +- **Answer:** +- **Uncertainty:** +- **Risks:** +- **Blockers:** + +| Finding | Evidence | Observation or inference | +| --- | --- | --- | +| | | | +``` diff --git a/plugins/aidd-dev/agents/validator.md b/plugins/aidd-dev/agents/validator.md index 3ed70e33a..0bb88a669 100644 --- a/plugins/aidd-dev/agents/validator.md +++ b/plugins/aidd-dev/agents/validator.md @@ -5,26 +5,30 @@ description: Validates an identified deliverable against supplied criteria and m # Role -Validate whether the supplied candidate satisfies its acceptance criteria and mandatory checks. +Validate an identified candidate against supplied criteria and mandatory checks. # Behavior -- Identify the candidate revision or artifact before checking it. Confirm the criteria and mandatory checks supplied by the caller or project. -- Use the smallest sufficient observable checks. Run every mandatory check. -- Record PASS, FAIL, or BLOCKED for each criterion and mandatory check with the supporting command output or artifact evidence. -- Mark missing, ambiguous, or unobservable criteria and missing prerequisites BLOCKED. An empty criteria set is blocked even if every command exits zero. -- Never infer completion from an implementer's claim. -- Confirm the candidate did not change during validation. If it changed, report affected evidence as stale. +- **Identify.** Record the candidate and confirm criteria, prerequisites, and mandatory checks. +- **Check.** Run every mandatory check and the smallest sufficient observable checks; record evidence for each result. +- **Complete.** Report COMPLETE only when all criteria and mandatory checks pass on an unchanged candidate. +- **Block.** Report BLOCKED for absent, ambiguous, or unobservable criteria, missing prerequisites, or stale evidence. +- **Fail.** Report INCOMPLETE for failures when no blocker prevents a reliable conclusion. +- **Boundary.** Never accept an implementer's claim as evidence, repair, change criteria, review quality, or delegate; normal temporary check artifacts are allowed. -# Outputs +# Output -Return the candidate identity, results and evidence, and one overall status: +Fill this Markdown template; replace placeholders and use `None` for empty fields. -- COMPLETE only when every criterion and mandatory check passed on the unchanged identified candidate. -- BLOCKED when criteria or prerequisites are missing, criteria are ambiguous or unobservable, or candidate evidence is stale. -- INCOMPLETE when checks failed and no blocker prevents a reliable conclusion. +```markdown +## Validation: -# Guardrails +- **Candidate:** +- **Status:** +- **Stability:** +- **Blockers:** -- Never repair the candidate or change its criteria. Checks may create their normal temporary artifacts, but must not rewrite the deliverable. -- Never perform a general quality review, delegate work, or invoke an orchestrator. +| Criterion or mandatory check | Result | Evidence | +| --- | --- | --- | +| | | | +``` diff --git a/plugins/aidd-dev/skills/01-plan/SKILL.md b/plugins/aidd-dev/skills/01-plan/SKILL.md index b0609c7ab..88fe5ad11 100644 --- a/plugins/aidd-dev/skills/01-plan/SKILL.md +++ b/plugins/aidd-dev/skills/01-plan/SKILL.md @@ -4,46 +4,28 @@ description: Turn a request, ticket, or file into a phased implementation plan. argument-hint: request | ticket | file --- -# Skill: plan +# Plan ```mermaid flowchart TD - Request([request, ticket, or file]) --> gather - gather --> explore - explore -- UI --> wireframe + Request([request, ticket, or file]) --> gather --> explore + explore -- UI --> wireframe --> plan explore -- no UI --> plan - wireframe --> plan - plan -- revision needed --> plan + plan -- challenge finds gaps --> plan plan --> Ready([plan ready]) ``` ## Actions -Read only the next matching numbered action file in `actions/`. +Read only the next numbered action file in `actions/`. | Action | Does | | --- | --- | -| gather | collect and restate the source | -| explore | ground the projection, rules, and feasibility | -| wireframe | sketch frontend screens at low fidelity | -| plan | write and review the plan and phase files | +| gather | identify the source and constraints | +| explore | ground scope and feasibility in evidence | +| wireframe | sketch frontend screens | +| plan | write and challenge phases | ## Transversal rules -- Planning never writes application code. - -Once the plan and its phase files are written, and only then, run: - -```shell -echo "aidd:step-end aidd-dev:01-plan" -``` - -## References - -- `references/wireframe-conventions.md`: how to draw the ASCII wireframe a screen needs. -- `references/plan-status.md`: the plan lifecycle `status` values and who writes each. - -## Assets - -- `assets/plan-template.md`: the `plan.md` scaffold. -- `assets/phase-template.md`: the per-phase scaffold. +- **Read-only.** Never write application code. diff --git a/plugins/aidd-dev/skills/01-plan/actions/01-gather.md b/plugins/aidd-dev/skills/01-plan/actions/01-gather.md index 22d9571cc..76c4a20e1 100644 --- a/plugins/aidd-dev/skills/01-plan/actions/01-gather.md +++ b/plugins/aidd-dev/skills/01-plan/actions/01-gather.md @@ -1,21 +1,18 @@ -# 01 - Gather - -Collect the source the plan will rest on, before any planning. Read only. +# Gather ## Input -The user's request, which may be empty. +A request, file, or ticket. ## Output -The source restated in a few bullets: what is asked and the hard constraints it states. The source kind and reference (file path, ticket id, or text) are named. +Source kind and reference, requested outcome, hard constraints. ## Process -1. **Find.** Identify what the request points to: a file path, a ticket URL or id, or raw text. When nothing concrete is given, ask once for a file, a ticket, or a description. Do not start without a source. -2. **Pull.** Read the file, fetch the ticket, or take the text as given. Never invent content the source does not contain. -3. **Restate.** Summarize the source in a few bullets: what is asked, and the hard constraints it states. No solution, no phases, no plan. +1. **Resolve.** Read the file, fetch the ticket, or use the supplied text; ask for a source if none exists. +2. **Restate.** Summarize the outcome and constraints in bullets with bold labels. -## Test +## Rules -- The output names the source kind and reference and restates it in bullets, states no solution, and when nothing concrete was given the user was asked before anything else. +- **Fidelity.** Invent no source content, solution, or phases. diff --git a/plugins/aidd-dev/skills/01-plan/actions/02-explore.md b/plugins/aidd-dev/skills/01-plan/actions/02-explore.md index f906d5301..95a0990cb 100644 --- a/plugins/aidd-dev/skills/01-plan/actions/02-explore.md +++ b/plugins/aidd-dev/skills/01-plan/actions/02-explore.md @@ -1,28 +1,23 @@ -# 02 - Explore - -Read the codebase to ground the plan: what it touches, which rules apply, what is feasible. Read only. +# Explore ## Input -The gathered source from `01-gather`. +The gathered source. ## Output -The architecture projection (files to modify, create, delete, each with a one-line reason), the project rules that apply (each justified in one line, or none), the feasibility checks (each source consulted, a doc URL or an in-repo file, and what it settled), and the risks. +- **Projection.** Files to modify, create, or delete, each with a reason. +- **Rules.** Applicable project rules and why, or none. +- **Evidence.** Sources consulted and what each settled. +- **Risks.** Blockers, conflicts, and unresolved questions. ## Process -1. **Read.** Explore the code the source touches and build the projection with its infrastructure assumptions. - - The primary caller may delegate independent, bounded read-only questions to available explorers when useful. Each returns references and unresolved questions. - - Reconcile their findings against the source before planning. Resolve conflicting claims or retain the uncertainty. An isolated agent never delegates again. -2. **Check.** Verify against the official docs or the in-repo code. Keep each source and what it settled. Flag blockers and risks. -3. **Select.** Keep the project rules that apply to the projection. +1. **Scope.** Identify the code and contracts the request touches. + - **Delegate.** The primary caller may assign independent questions by relevant codebase domain, such as frontend, backend, or a bounded context, to available explorers; give each a scope and requested evidence. +2. **Verify.** Check feasibility against in-repo code or official documentation. +3. **Reconcile.** Combine findings into the projection and applicable rules; resolve conflicting claims with evidence or retain the uncertainty. -## Test +## Rules -| Case | Pass | -| --- | --- | -| The exploration completes | The projection names files to modify, create, and delete with reasons; applicable rules are justified or none apply. | -| A feasibility claim is made | Its source and what it settled are recorded. | -| Exploration is delegated | Returned references and unresolved questions are reconciled into the projection and risks. | -| Sources disagree | The conflict is resolved with evidence or remains explicit as uncertainty. | +- **Boundaries.** Explore only relevant domains; delegation is optional and isolated agents never delegate again. diff --git a/plugins/aidd-dev/skills/01-plan/actions/03-wireframe.md b/plugins/aidd-dev/skills/01-plan/actions/03-wireframe.md index 928b9cb95..81ac7a5a0 100644 --- a/plugins/aidd-dev/skills/01-plan/actions/03-wireframe.md +++ b/plugins/aidd-dev/skills/01-plan/actions/03-wireframe.md @@ -1,20 +1,14 @@ -# 03 - Wireframe - -Sketch a low-fidelity ASCII wireframe of a screen, to fix its layout before the plan. Frontend only, skip it when the feature has no UI. +# Wireframe ## Input -The screens to sketch, from the gathered source and the `02-explore` context (the existing screens and components). +Required screens and existing components from exploration. ## Output -A low-fidelity ASCII wireframe of each screen, its regions and key elements in place, with a numbered note per region. Structure only, no behavior, no styling, no final copy. +An ASCII wireframe per screen, with numbered regions and one-line notes. ## Process -1. **Pick.** List the screens the feature needs. Skip the action entirely when there is no UI. -2. **Draw.** Sketch each screen per [wireframe-conventions.md](../references/wireframe-conventions.md). The wireframe feeds the plan. - -## Test - -- The output is a box-drawing wireframe of each screen with numbered regions and a one-line note each, carrying no behavior, styling, or final copy. +1. **Select.** Identify required screens; skip when there is no UI. +2. **Draw.** Follow [wireframe-conventions.md](../references/wireframe-conventions.md). diff --git a/plugins/aidd-dev/skills/01-plan/actions/04-plan.md b/plugins/aidd-dev/skills/01-plan/actions/04-plan.md index b431aae05..d32737c9c 100644 --- a/plugins/aidd-dev/skills/01-plan/actions/04-plan.md +++ b/plugins/aidd-dev/skills/01-plan/actions/04-plan.md @@ -1,51 +1,34 @@ -# 04 - Plan - -Turn the explored source into a plan and its phases, save them, then review the whole before handoff. Never code. +# Plan ## Input -The explore output from `02-explore` (projection, rules, feasibility, risks), plus any confirmed wireframe from `03-wireframe`. +Exploration findings and any wireframes. ## Output -A feature folder, always at `aidd_docs/tasks//_/`, holding `plan.md` from [plan-template.md](../assets/plan-template.md) and one `phase-.md` per phase from [phase-template.md](../assets/phase-template.md). +`plan.md` and `phase-.md` files in the source's feature folder or `aidd_docs/tasks//_/`. ## Process -1. **Phases.** Break the work into phases, each a coherent unit of work that ships and verifies on its own, sized for one executor pass. Let the work decide how many. - - Prefer independent phases without splitting inseparable work. - - Identify prerequisites from each phase's file projection, shared contracts, and validation resources. - - Order phases that need another phase's output or would interfere through shared file changes or mutable validation resources. - - Preserve ordering when independence cannot be established. -2. **Folder.** Reuse the feature folder the source already lives in, or create one. When creating one and `01-gather`'s own source reference names a backlog item — a ticket id or URL, or a file path naming its Markdown artefact, never raw text — with no `backlog-link.json` there yet, declare it the same way the skill that writes a spec does: +1. **Slice.** Prefer independent phases, each coherent, verifiable, and sized for one executor pass. +2. **Write.** Fill [plan-template.md](../assets/plan-template.md) and [phase-template.md](../assets/phase-template.md), covering the full projection without placeholders. +3. **Link.** For a new folder whose source reference names a backlog item, create `backlog-link.json`: ```json - { - "backlog": "owner/repo#123", - "written_at": "2026-08-21T09:00:00Z", - "written_by": "aidd-dev:01-plan" - } + {"backlog": "", "written_at": "", "written_by": "aidd-dev:01-plan"} ``` - `backlog` is the one field, on whatever support the item lives - a forge reference or a project-relative Markdown path, never both. When the source names none, write nothing. When `backlog-link.json` already exists, leave it untouched - it is correctable by hand, and a later run must never overwrite a correction. -3. **Fill.** Fill the plan and each phase from their templates, following the inline contracts, and record prerequisites in the phase table. - - Slice the projection across the phases. -4. **Show.** Display the written paths. -5. **Review.** Check the declared dependencies against the phase scopes, then score the complete plan and its phases from 0 to 10, with ✓ reasons and ✗ risks. - - In interactive mode, show them and revise until approved. - - Under an autonomous orchestrator, revise against the source without waiting for approval; ask only when a product decision cannot be resolved from the source. - - Never write the score to the plan. - -## Test - -| Case | Pass | -| --- | --- | -| The plan is written | The feature folder holds `plan.md` and one `phase-.md` per phase. | -| Written files are read back | Each satisfies its template's inline contract with no `{...}` placeholder left. | -| Phase projections are combined | They cover the modify, create, and delete lists. | -| Dependencies are reviewed | Every prerequisite names an existing earlier phase; no phase depends on itself. | -| Phases share a required output, conflicting file changes, or mutable validation resources | Their ordering is recorded in the phase table. | -| Phase independence is uncertain | The plan preserves ordering. | -| The plan is scored | A confidence score was reported and written to no file. | -| The run is autonomous | It waits only for a product decision that the source cannot resolve. | -| A new folder's source names a ticket | `backlog-link.json` names it; reusing a folder never overwrites an existing link. | +4. **Challenge.** Check source coverage, phase boundaries, acceptance criteria, and dependencies; revise gaps, using an available challenge capability when useful. + - **Interactive.** Show paths and obtain approval. + - **Autonomous.** Ask only for product decisions the source cannot resolve. +5. **Finish.** Emit the completion marker once the files are written and challenged. + + ```shell + echo "aidd:step-end aidd-dev:01-plan" + ``` + +## Rules + +- **Dependencies.** Record earlier phase numbers in `Depends on` for required outputs, conflicting file changes, or shared mutable validation resources; preserve ordering when independence is uncertain. +- **Link preservation.** Never overwrite an existing backlog link; `backlog` holds one forge reference or project-relative Markdown path, never both or inferred from raw text. +- **Lifecycle.** Follow [plan-status.md](../references/plan-status.md). diff --git a/plugins/aidd-dev/skills/01-plan/references/plan-status.md b/plugins/aidd-dev/skills/01-plan/references/plan-status.md index 59442bb8b..3480af0e3 100644 --- a/plugins/aidd-dev/skills/01-plan/references/plan-status.md +++ b/plugins/aidd-dev/skills/01-plan/references/plan-status.md @@ -17,7 +17,7 @@ The plan's `status` frontmatter field tracks its lifecycle for kanban views. The ## Rules -- Linear: `pending → in-progress → implemented → reviewed`. `blocked` is reachable from any active state. -- Review reject (`iterate` / `changes-requested`) does NOT set `reviewed`. The plan stays `implemented` while the loop fixes the diff, not the plan. -- `implemented` ≠ reviewed. Only the review layer sets `reviewed`. -- Assigned phase workers never write the plan status. They may update only their own phase status; the whole-plan owner updates the plan. +- **Transitions.** `pending → in-progress → implemented → reviewed`. `blocked` is reachable from any active state. +- **Rejection.** Review reject (`iterate` / `changes-requested`) does NOT set `reviewed`. The plan stays `implemented` while the loop fixes the diff, not the plan. +- **Review ownership.** `implemented` ≠ reviewed. Only the review layer sets `reviewed`. +- **Phase ownership.** Assigned phase workers never write the plan status. They may update only their own phase status; the whole-plan owner updates the plan. diff --git a/plugins/aidd-dev/skills/01-plan/references/wireframe-conventions.md b/plugins/aidd-dev/skills/01-plan/references/wireframe-conventions.md index 1dfb23947..9156451fe 100644 --- a/plugins/aidd-dev/skills/01-plan/references/wireframe-conventions.md +++ b/plugins/aidd-dev/skills/01-plan/references/wireframe-conventions.md @@ -4,10 +4,10 @@ A wireframe is a low-fidelity ASCII sketch of a screen. Structure only: no behav ## Drawing -- One box per screen, drawn with `┌ ─ ┐ │ └ ┘`. -- Place the regions (header, nav, main, aside, footer) and the key elements (lists, forms, cards, buttons, inputs) where they sit. -- Number each region. -- Under the sketch, one line per number on what it holds and why. +- **Screen.** One box per screen, drawn with `┌ ─ ┐ │ └ ┘`. +- **Layout.** Place the regions (header, nav, main, aside, footer) and the key elements (lists, forms, cards, buttons, inputs) where they sit. +- **Regions.** Number each region. +- **Notes.** Under the sketch, one line per number on what it holds and why. ## Example diff --git a/plugins/aidd-dev/skills/02-implement/SKILL.md b/plugins/aidd-dev/skills/02-implement/SKILL.md index e07d2af44..deb3c7985 100644 --- a/plugins/aidd-dev/skills/02-implement/SKILL.md +++ b/plugins/aidd-dev/skills/02-implement/SKILL.md @@ -4,41 +4,34 @@ description: Implements an existing plan or an assigned phase until its acceptan argument-hint: plan | phase --- -# Skill: implement +# Implement ```mermaid flowchart TD Whole([whole plan]) --> prepare Assigned([assigned phase]) --> execute prepare --> execute - execute -- check failed, repair --> execute - execute -- more ready phases --> execute - execute -- assigned phase complete --> Returned([return phase and evidence]) - execute -- whole plan complete --> finalize - finalize -- validation failed, repair affected scope --> execute - finalize --> Implemented([implemented]) prepare -- plan missing --> Missing([stop]) - execute -- blocked or drift --> Stopped([report blocker or replan needed]) + execute -- repair or more ready phases --> execute + execute -- assigned phase done --> Returned([return evidence]) + execute -- whole plan done --> finalize + execute -- blocked or drift --> Stopped([report blocker or replan]) + finalize -- repair --> execute + finalize --> Implemented([implemented]) ``` ## Actions -Read only the next matching numbered action file in `actions/`. +Read only the next numbered action file in `actions/`. | Action | Does | | --- | --- | -| prepare | resolve the whole plan and prepare its branch | -| execute | implement and validate the selected scope | -| finalize | verify the integrated plan and mark it implemented | +| prepare | resolve the plan and prepare its branch | +| execute | implement and check assigned scope | +| finalize | validate the integrated plan | ## Transversal rules -- Supplying a whole plan assigns lifecycle-status ownership of that plan and its phases to the whole-plan runner. Supplying an assigned phase grants only that phase's lifecycle-status ownership. Neither grant permits changes to scope, specifications, or criteria. -- A whole-plan run owns integration and completion verification. An assigned-phase run enters execute directly and returns without prepare or finalize. The primary caller retains final acceptance. -- Phase status follows `pending → in-progress → done`. The whole-plan owner drives `pending → in-progress → implemented` or `blocked`. Runtime markers need no separate commit. -- Follow the caller's commit policy. When commits are authorized, commit each phase's code with its own `done` status and the final plan status separately. Keep unrelated changes out of these commits. -- Isolated agents never spawn agents. Only the primary caller may delegate bounded work using available host capabilities. - -## References - -- `references/blocked.md`: conditions requiring a human. +- **Ownership.** Whole-plan runners own integration and plan/phase lifecycle statuses; assigned-phase runners own only their phase status and skip prepare/finalize. Never change requirements or criteria; the caller retains final acceptance. +- **Commits.** Follow caller policy; when authorized, commit each phase's code with its `done` status and the final plan status separately, excluding unrelated changes. Runtime markers need no separate commit. +- **Delegation.** Only the primary caller may delegate; isolated agents never spawn agents. diff --git a/plugins/aidd-dev/skills/02-implement/actions/01-prepare.md b/plugins/aidd-dev/skills/02-implement/actions/01-prepare.md index 8171926c0..7c6000662 100644 --- a/plugins/aidd-dev/skills/02-implement/actions/01-prepare.md +++ b/plugins/aidd-dev/skills/02-implement/actions/01-prepare.md @@ -1,24 +1,19 @@ -# 01 - Prepare - -Resolve the plan, put the workspace on a feature branch, and mark the plan in-progress. +# Prepare ## Input -A whole plan, passed as arguments as a path or inline content. +A whole plan, as a path or inline content. ## Output -The resolved plan on a feature branch with its frontmatter `status: in-progress`, ready for the phase loop. Or a fail-fast stop when no plan resolves. +Resolved plan on a feature branch, `status: in-progress`, or a missing-plan error. ## Process -1. **Resolve.** Resolve the plan from the arguments. A path must exist and be readable. With neither a readable file nor inline content, stop with `plan not found at `. Never fabricate a plan. -2. **Branch.** On the default branch, create a feature branch and announce it. On a non-default branch, keep it. -3. **Mark.** Set the plan frontmatter `status: in-progress` as a runtime marker. Leave shared plan updates to the whole-plan owner; they follow the caller's commit policy. +1. **Resolve.** Read the supplied plan; if unavailable, stop with `plan not found at `. +2. **Branch.** Create and announce a feature branch when on the default branch; otherwise keep the current branch. +3. **Mark.** Set the plan `status: in-progress`. -## Test +## Rules -| Case | Pass | -| --- | --- | -| No readable plan or inline content resolves | Execution stops with `plan not found at `; no plan is fabricated. | -| Preparation succeeds | The current branch is not the default branch and the plan status is in-progress. | +- **Source.** Never fabricate a missing plan. diff --git a/plugins/aidd-dev/skills/02-implement/actions/02-execute.md b/plugins/aidd-dev/skills/02-implement/actions/02-execute.md index 952d59fe1..44ecf2dc1 100644 --- a/plugins/aidd-dev/skills/02-implement/actions/02-execute.md +++ b/plugins/aidd-dev/skills/02-implement/actions/02-execute.md @@ -1,39 +1,25 @@ -# 02 - Execute +# Execute ## Input -A prepared whole plan, or an assigned phase whose file is included in the assigned scope, with its plan context, completed prerequisites, acceptance criteria, checkout, and commit policy. +A prepared plan or assigned phase, with plan context, prerequisites, criteria, checkout, resources, and commit policy. ## Output -The selected phases implemented with passing checks, `status: done`, and evidence identifying the checked revision. Or a blocker or `replan needed` report. +Implemented phases, `status: done`, check commands/results and checked revision, or a blocker/replan report. ## Process -1. **Select.** Resolve the execution scope and its prerequisites before changing files. - - Assigned phase: implement only that phase. Require a distinct checkout and nonconflicting validation resources when other executors run concurrently. Do not restart the plan, update its shared status, or run finalization. - - Whole plan: select phases whose `Depends on` prerequisites are done and integrated. Check file projections, shared contracts, and mutable validation resources before the primary caller dispatches a parallel batch to available executors. Give each ownership of its phase file for lifecycle-status updates only, completed prerequisites, criteria, isolated checkout, resources, and commit policy. - - Execute serially when isolation is unavailable or independence is uncertain. A plan without declared dependencies runs in phase order. - - Report `replan needed` for missing or contradictory prerequisites, or when unfinished phases have no ready phase; never skip them to declare completion. -2. **Code.** Mark the selected phase `in-progress` and implement only its projection against its acceptance criteria. -3. **Assert.** Run the relevant phase checks, repair failures, and repeat until they pass. - - Then mark the phase `done` and deliver its code, phase status, check commands, results, and checked revision under the caller's commit policy. - - The whole-plan owner integrates returned work before considering a dependency complete. Run checks for interactions changed by integration; reserve full plan validation for finalize. Select the next ready phases until all are done. -4. **Guard.** Stop affected work on a blocker or any scope drift. - - **Blocked:** apply [blocked.md](../references/blocked.md); an assigned executor reports to the caller, while the whole-plan owner marks the plan `blocked`. - - **Drift:** report `replan needed: ` without rewriting the plan or criteria. The caller decides how to revise the plan before resuming dependent work. - -## Test - -| Case | Pass | -| --- | --- | -| An assigned phase runs | Only its code and owned phase lifecycle status change; prepare, shared plan updates, other phases, and finalize are not run. | -| A whole-plan executor runs | It updates only lifecycle statuses in supplied plan and phase files; scope, specifications, and criteria remain unchanged. | -| A prerequisite is unfinished | Its dependent phase is not started. | -| Prerequisites are missing or contradictory | Execution stops for replanning without marking unfinished phases done. | -| A parallel batch runs | File changes and mutable validation resources do not conflict; executors use distinct checkouts and Git indexes. | -| Isolation or independence is uncertain | Execution is serial. | -| The plan has no dependency declarations | Phases run in their original order. | -| A phase reaches done | Its criteria pass and the returned evidence identifies the checked revision. | -| A returned phase has dependents | Its changes are integrated before any dependent starts. | -| A blocker or scope drift occurs | Affected work stops; an assigned executor reports without rewriting shared plan state. | +1. **Select.** Run only assigned or whole-plan phases whose prerequisites are done and integrated. + - **Parallel.** The primary caller may dispatch independent phases to executors with their owned files, criteria, completed prerequisites, distinct checkouts/Git indexes, and nonconflicting validation resources. + - **Serial.** Run in order when isolation or independence is uncertain, or dependencies are undeclared. +2. **Implement.** Mark the phase `in-progress`, implement its projection, check its criteria, and repair until passing. +3. **Deliver.** Mark the phase `done` and return its changes and evidence. + - **Whole plan.** Integrate returned work, recheck affected interactions, and select the next ready phases. + - **Assigned phase.** Return to the caller. + +## Rules + +- **Readiness.** Missing/contradictory dependencies or unfinished phases with none ready require `replan needed`; never skip them or declare completion. +- **Drift.** Stop affected work and report `replan needed: ` without rewriting scope or criteria. +- **Blocked.** Follow [blocked.md](../references/blocked.md); assigned executors report, the whole-plan owner sets plan `status: blocked`. diff --git a/plugins/aidd-dev/skills/02-implement/actions/03-finalize.md b/plugins/aidd-dev/skills/02-implement/actions/03-finalize.md index bf5ccfb19..d3970fdb2 100644 --- a/plugins/aidd-dev/skills/02-implement/actions/03-finalize.md +++ b/plugins/aidd-dev/skills/02-implement/actions/03-finalize.md @@ -1,28 +1,19 @@ -# 03 - Finalize - -Run the validation and mark the plan implemented once every phase is done. +# Finalize ## Input -A plan whose phases are all `status: done`, from `02-execute`. +A plan with all phases done and integrated. ## Output -The feature validated green with the plan frontmatter `status: implemented`. +Plan `status: implemented`, with integrated acceptance and validation evidence. ## Process -1. **Verify.** Verify every plan-level acceptance criterion and required validation against the integrated candidate. - - Phase checks alone do not establish that the combined workflow works. - - Reuse a passing result only when it covers the same candidate and required scope; rerun checks invalidated by later changes or integration. Never format code or run dev mode. - - On failure, return the affected scope to execution and verify the repaired candidate before marking completion. -2. **Mark.** Set the plan `status: implemented` only when every phase is done and integrated validation is green, then deliver under the caller's commit policy. +1. **Verify.** Check every plan-level acceptance criterion and required validation on the integrated candidate; return failures to execution and revalidate repairs. +2. **Mark.** Set the plan `status: implemented` only when all required checks pass. -## Test +## Rules -| Case | Pass | -| --- | --- | -| Finalization succeeds | Every phase is done and the required validation covers the integrated candidate with passing results. | -| A previous result is reused | Its candidate and required scope match; changed candidates invalidate affected checks. | -| Validation fails | The plan is not marked implemented; affected work returns for repair. | -| The plan reaches implemented | Its status is delivered under the caller's commit policy. | +- **Evidence.** Reuse passing results only for the same candidate and required scope; phase checks alone do not establish integrated acceptance. +- **Validation scope.** Never format code or run dev mode during finalization. diff --git a/plugins/aidd-orchestrator/skills/01-sdlc/references/02-deliver.md b/plugins/aidd-orchestrator/skills/01-sdlc/references/02-deliver.md index d7b8192fd..e9ecb3ab1 100644 --- a/plugins/aidd-orchestrator/skills/01-sdlc/references/02-deliver.md +++ b/plugins/aidd-orchestrator/skills/01-sdlc/references/02-deliver.md @@ -2,13 +2,10 @@ ## Behavior -Turn the contract into a proportional plan. Delegate bounded read-only exploration when useful and reconcile sources and unknowns before planning. - -Own preparation, shared plan status, dependencies, integration, and finalization. Assign ready, independent phases to executors in distinct checkouts with nonconflicting validation resources. Include each assigned phase file in its scope for lifecycle-status updates only, alongside plan context, criteria, completed prerequisites, and commit policy. Run sequentially when isolation is unavailable or independence is uncertain; legacy plans retain their phase order. For a sequential whole-plan executor, grant lifecycle-status ownership of the plan and all its phases while retaining acceptance; never grant changes to scope, specifications, or criteria. - -Executors implement, validate, and repair only their assigned scope without further delegation. Include architecture conformance when documented. Integrate each returned phase before starting its dependents. Finalize against the integrated candidate, including any required end-to-end journey last. Preserve passing evidence only when its candidate and scope still match. - -Commit and push through the commit capability. Send the clean committed candidate and its validation evidence to Check. +- **Plan:** reconcile scoped exploration, then produce the implementation plan. +- **Assign:** retain shared lifecycle and integration; delegate independent phases with their criteria, prerequisites, status-file ownership, checkout, resources, and commit policy. Use separate checkouts for parallel writers; otherwise run serially. A whole-plan executor may own all lifecycle statuses, never scope or criteria. +- **Integrate:** accept scoped changes and evidence before starting dependents; finalize against the combined candidate, with required end-to-end checks last. Reuse only evidence still valid for that candidate and scope. +- **Handoff:** commit and push through the commit capability; send the clean candidate and evidence to Check. ```mermaid --- diff --git a/plugins/aidd-orchestrator/skills/01-sdlc/references/03-check.md b/plugins/aidd-orchestrator/skills/01-sdlc/references/03-check.md index 38b042aa5..481165fee 100644 --- a/plugins/aidd-orchestrator/skills/01-sdlc/references/03-check.md +++ b/plugins/aidd-orchestrator/skills/01-sdlc/references/03-check.md @@ -2,11 +2,10 @@ ## Behavior -Use a fresh validator independent from implementation to verify the identified committed candidate against the contract, plan criteria, and mandatory checks. Require PASS, FAIL, or BLOCKED per criterion with evidence. The validator does not repair. - -Only after validation passes, use a fresh checker to review quality, risks, and fitness against the contract, plan, and validation evidence. Repeat targeted checks only when evidence is missing, inconsistent, or stale. After review clears, the same checker challenges the outcome. Any repaired candidate returns to independent validation; neither judgment carries forward automatically. - -Use product or contract findings as the next Frame source. Dispatch independent implementation findings through Todo and keep dependent repairs together in Deliver. Re-enter Check after every new candidate. Open the draft pull request when the checker returns no actionable finding. +- **Validate:** dispatch a fresh validator on the committed candidate, contract, criteria, and mandatory checks. +- **Challenge:** after validation passes, dispatch a fresh checker for review and outcome challenge using that evidence. +- **Route:** send product findings to Frame, independent repairs to Todo, dependent repairs to Deliver; revalidate each repaired candidate. +- **Ship:** open the draft pull request when no actionable finding remains. ```mermaid --- diff --git a/scripts/dev-sync.sh b/scripts/dev-sync.sh index 21db8d3ee..f9af1c402 100755 --- a/scripts/dev-sync.sh +++ b/scripts/dev-sync.sh @@ -9,6 +9,19 @@ # # Codex caveat: the .codex-plugin manifest does not declare codex-agents/*.toml, and Codex # loads agents only from ~/.codex/agents/, so the built TOML is copied there after install. +# Global rules: replace only the managed AIDD block; exclude project memory and adapt agent +# names. First OpenCode sync keeps its Claude personal-rule fallback unless disabled. +# Instruction paths honor CODEX_HOME, CLAUDE_CONFIG_DIR and XDG_CONFIG_HOME; tests use +# *_INSTRUCTIONS overrides. Sources checked 2026-10-14: +# https://developers.openai.com/codex/guides/agents-md +# https://code.claude.com/docs/en/memory +# https://opencode.ai/docs/rules/ +# OpenCode V2 discovery: global agents are filename-named subagents; inspect with +# `opencode debug agents`. File presence alone does not prove invocation or permissions. +# https://opencode.ai/v2/docs/agents (read 2026-10-14) +# https://github.com/anomalyco/opencode/blob/v2.0.28/packages/core/src/config/plugin/agent.ts +# V2.0.28 probe cwd must match PWD because run prefers PWD (read 2026-10-14): +# https://github.com/anomalyco/opencode/blob/v2.0.28/packages/cli/src/run/run.ts set -euo pipefail shopt -s nullglob @@ -41,6 +54,7 @@ build_tool() { } validate_opencode_content() { + # Check every expected nonempty skill and agent before replacing selected namespaces. local name agent skill skill_name for name in "$@"; do for skill in "$FW/plugins/$name/skills/"*/SKILL.md; do @@ -61,6 +75,7 @@ validate_opencode_content() { } sync_opencode_skills() { + # Accept nested and legacy flat builds; preserve personal and unselected plugin content. local name source skill destination local -a skills mkdir -p "$OPENCODE_SKILLS" From e04e3e33093c86645a9bd3e0ed28011288797020 Mon Sep 17 00:00:00 2001 From: alexsoyes Date: Wed, 14 Oct 2026 16:53:10 +0800 Subject: [PATCH 08/73] fix(framework): align workflow contracts and remove repeated instructions --- .../skills/04-skill-generate/SKILL.md | 8 ++-- .../04-skill-generate/actions/01-scope.md | 14 +----- .../04-skill-generate/actions/02-plan.md | 25 ++++------ .../04-skill-generate/actions/03-write.md | 27 ++++------- .../04-skill-generate/actions/04-validate.md | 14 ++---- .../assets/action-template.md | 8 ++-- .../assets/skill-template.md | 2 +- .../references/scope-frame.md | 30 ++++-------- .../references/skill-authoring.md | 8 ++-- .../02-implement/actions/03-finalize.md | 2 +- .../skills/01-sdlc/references/02-deliver.md | 15 +++--- plugins/aidd-refine/CATALOG.md | 3 +- plugins/aidd-refine/README.md | 2 +- .../aidd-refine/skills/02-challenge/SKILL.md | 29 ++++------- .../02-challenge/actions/01-challenge.md | 34 +++++-------- .../02-challenge/assets/report-template.md | 25 ++++++---- .../references/confidence-rubric.md | 10 ---- scripts/__tests__/dev-sync.test.js | 48 +++++++++++++++---- scripts/dev-sync.sh | 6 +-- scripts/sync-global-instructions.cjs | 7 +-- 20 files changed, 139 insertions(+), 178 deletions(-) delete mode 100644 plugins/aidd-refine/skills/02-challenge/references/confidence-rubric.md diff --git a/plugins/aidd-context/skills/04-skill-generate/SKILL.md b/plugins/aidd-context/skills/04-skill-generate/SKILL.md index 6e546fb72..4f6e262f1 100644 --- a/plugins/aidd-context/skills/04-skill-generate/SKILL.md +++ b/plugins/aidd-context/skills/04-skill-generate/SKILL.md @@ -25,7 +25,7 @@ Run the flow above. Read only the next action file. ## Transversal rules -- Default to `create`; follow `modify` when asked. -- If a cited reference cannot be read, stop and report the missing file. -- Confirm every target and name with the user. -- Never write silently. +- **Entry.** Default to `create`; follow `modify` when asked. +- **References.** If a cited reference cannot be read, stop and report the missing file. +- **Confirmation.** Confirm every target and name with the user. +- **Visibility.** Never write silently. diff --git a/plugins/aidd-context/skills/04-skill-generate/actions/01-scope.md b/plugins/aidd-context/skills/04-skill-generate/actions/01-scope.md index 2ed28f681..d7f85953c 100644 --- a/plugins/aidd-context/skills/04-skill-generate/actions/01-scope.md +++ b/plugins/aidd-context/skills/04-skill-generate/actions/01-scope.md @@ -13,16 +13,6 @@ The confirmed frame, written nowhere, per [scope-frame.md](../references/scope-f ## Process 1. **Detect.** Detect the installed tools per [tool-detect.md](../references/tool-detect.md). -2. **Fill.** For each field in [scope-frame.md](../references/scope-frame.md), propose a value or ask one question. -3. **Check.** Check the name per [naming.md](../references/naming.md) and surface any overlap. +2. **Fill.** For each field in [scope-frame.md](../references/scope-frame.md), propose a value or ask one question at a time. +3. **Check.** Check the name per [naming.md](../references/naming.md), reporting overlaps or none. 4. **Confirm.** Hand the confirmed frame to plan. - -## Test - -| Case | Pass | -| --- | --- | -| The action runs to completion | `git status --porcelain` reads the same after as before | -| A name overlaps an installed skill | the overlap is surfaced before the frame is handed on | -| No name overlaps | the run states that it found none | -| A frame field needs the user | one question is asked, and only that one | -| The frame is handed to plan | its target was confirmed by the user first | diff --git a/plugins/aidd-context/skills/04-skill-generate/actions/02-plan.md b/plugins/aidd-context/skills/04-skill-generate/actions/02-plan.md index 41c70fa72..baaf0f3cd 100644 --- a/plugins/aidd-context/skills/04-skill-generate/actions/02-plan.md +++ b/plugins/aidd-context/skills/04-skill-generate/actions/02-plan.md @@ -1,27 +1,20 @@ # 02 - Plan -Break the skill into atomic, testable actions: one action, one job. +Break the skill into atomic actions: one action, one job. ## Input -- From scope, the create frame. -- For a modify, the existing skill, read in place. +- **Create.** The frame from scope. +- **Modify.** The existing skill, read in place. ## Output -A plan table, one row per action: slug, input to output, test, and any dependency. +A plan table, one row per action: slug, input to output, observable success, and dependencies. ## Process -1. **List.** List every distinct job the output needs. Modify: start from the existing actions, touch only the jobs the user named. -2. **Atomize.** Prefer few actions, a job each, not a step. Merge two that share most logic. -3. **Number.** Name, number, and give each an observable test, per [skill-authoring.md](../references/skill-authoring.md). -4. **Confirm.** Present the table, validate each test with the user. - -## Test - -| Case | Pass | -| --- | --- | -| The table is presented | every row is one job carrying a checkable test | -| A row consumes an output | that output comes from an earlier row, never a later one | -| The run is a modify | only the jobs the user named have a row | +1. **List.** List every distinct job the output needs. + - **Modify.** Keep only jobs the user named. +2. **Atomize.** Prefer few actions, a job each; merge two that share most logic. +3. **Order.** Name and number each action per [skill-authoring.md](../references/skill-authoring.md), placing consumed outputs before their consumers. +4. **Confirm.** Present the table and confirm each observable success condition with the user. diff --git a/plugins/aidd-context/skills/04-skill-generate/actions/03-write.md b/plugins/aidd-context/skills/04-skill-generate/actions/03-write.md index 595826e48..eefe567a9 100644 --- a/plugins/aidd-context/skills/04-skill-generate/actions/03-write.md +++ b/plugins/aidd-context/skills/04-skill-generate/actions/03-write.md @@ -4,8 +4,8 @@ Write the skill tree from the plan. ## Input -- The plan from 02. -- The target from 01, or for a modify the existing skill's own location. +- **Plan.** The plan from 02. +- **Target.** The target from 01, or for a modify the existing skill's own location. ## Output @@ -14,21 +14,10 @@ The skill tree at the target, and the list of files written. ## Process 1. **Tree.** Create the shape in [skill-tree.md](../references/skill-tree.md). -2. **Router.** Fill [skill-template.md](../assets/skill-template.md) against [skill-authoring.md](../references/skill-authoring.md), strip the scaffold. - - Modify: revise the existing SKILL.md in place, keeping the user's edits. -3. **Actions.** Fill [action-template.md](../assets/action-template.md) per row against [skill-authoring.md](../references/skill-authoring.md), its test copied from the plan. - - Modify: revise a changed action in place. Leave an untouched one alone. +2. **Router.** Fill [skill-template.md](../assets/skill-template.md) against [skill-authoring.md](../references/skill-authoring.md). + - **Modify.** Revise the existing SKILL.md in place, keeping the user's edits. +3. **Actions.** Fill [action-template.md](../assets/action-template.md) per row, weaving its success check into the process. + - **Modify.** Revise changed actions in place; leave untouched ones alone. 4. **Hint.** Set `argument-hint` per [skill-authoring.md](../references/skill-authoring.md). -5. **Place.** Write once per confirmed target, using [tool-write.md](../references/tool-write.md). -6. **Check.** Confirm every written path is relative, inside the workspace, outside the plugin install directory, and under the chosen target. Else stop and report it. - -## Test - -| Case | Pass | -| --- | --- | -| The router is written | it holds a `mermaid` flowchart and an `Action \| Does` table | -| The action table is read back | every slug is bare and every `Does` is a lowercase imperative with no final period | -| An action file is written | it holds `## Output`, `## Process`, and a `Case \| Pass` `## Test` | -| The tree is written | its shape matches [skill-tree.md](../references/skill-tree.md) | -| Any written file is read back | no `<` placeholder and no template instruction line survives | -| A path resolves outside the chosen target | the run stops and reports that path | +5. **Place.** Write once per confirmed target using [tool-write.md](../references/tool-write.md), stopping if a path escapes the workspace or target or enters a plugin install directory. +6. **Read back.** Check the tree and every file against the contract, removing placeholders and scaffold instructions before validation. diff --git a/plugins/aidd-context/skills/04-skill-generate/actions/04-validate.md b/plugins/aidd-context/skills/04-skill-generate/actions/04-validate.md index fca3dacbb..9f9af8f1e 100644 --- a/plugins/aidd-context/skills/04-skill-generate/actions/04-validate.md +++ b/plugins/aidd-context/skills/04-skill-generate/actions/04-validate.md @@ -8,18 +8,10 @@ The skill written by 03. ## Output -A report, one row per file: what was checked and any fix applied. +A report, one row per written file: checks, findings or none, and fixes applied. ## Process 1. **Review.** Review each file against [review-protocol.md](../references/review-protocol.md). -2. **Fix.** Apply the confirmed fixes on disk, then re-review the changed files. -3. **Report.** Deliver the findings, even when clean. - -## Test - -| Case | Pass | -| --- | --- | -| The report is delivered | every written file has a row, with its findings or none | -| The review finds a breach | it names the broken rule and a `file:line` | -| A fix is confirmed | the file differs on disk and is reviewed again | +2. **Fix.** Apply the confirmed fixes on disk, read them back, and re-review until no breach remains. +3. **Report.** Deliver the report, even when clean. diff --git a/plugins/aidd-context/skills/04-skill-generate/assets/action-template.md b/plugins/aidd-context/skills/04-skill-generate/assets/action-template.md index be7d9cc99..5cd1e1637 100644 --- a/plugins/aidd-context/skills/04-skill-generate/assets/action-template.md +++ b/plugins/aidd-context/skills/04-skill-generate/assets/action-template.md @@ -13,12 +13,10 @@ ## Process 1. **