From f899efab11a232fce5e27e6053e52ba89b709c9e Mon Sep 17 00:00:00 2001 From: Alex Verkhovsky Date: Sun, 8 Mar 2026 04:54:22 -0600 Subject: [PATCH] feat(tasks): convert review-adversarial-general from XML task to native skill Convert the simplest core task (review-adversarial-general.xml) from type:task XML format to type:skill markdown format. This establishes the pattern for converting remaining XML tasks to self-contained skills. - Convert XML task to workflow.md with frontmatter, role, execution steps - Add type:skill manifest for verbatim directory copying - Extend manifest-generator getTasksFromDir to recurse into subdirectories and detect type:skill entries (mirrors existing workflow skill detection) - Update cross-references in quick-dev-new-preview, quick-dev, quick-spec - Update module-help.csv to use skill: prefix --- .../steps/step-04-review.md | 2 +- .../bmad-quick-dev-new-preview/workflow.md | 2 +- .../steps/step-05-adversarial-review.md | 2 +- .../quick-spec/steps/step-04-review.md | 2 +- src/core/module-help.csv | 2 +- .../bmad-skill-manifest.yaml | 1 + .../workflow.md | 37 ++++++++++++++ src/core/tasks/bmad-skill-manifest.yaml | 5 -- src/core/tasks/review-adversarial-general.xml | 49 ------------------- .../installers/lib/core/manifest-generator.js | 43 +++++++++++++++- 10 files changed, 84 insertions(+), 61 deletions(-) create mode 100644 src/core/tasks/bmad-review-adversarial-general/bmad-skill-manifest.yaml create mode 100644 src/core/tasks/bmad-review-adversarial-general/workflow.md delete mode 100644 src/core/tasks/review-adversarial-general.xml diff --git a/src/bmm/workflows/bmad-quick-flow/bmad-quick-dev-new-preview/steps/step-04-review.md b/src/bmm/workflows/bmad-quick-flow/bmad-quick-dev-new-preview/steps/step-04-review.md index e13e7652c..a5a6db951 100644 --- a/src/bmm/workflows/bmad-quick-flow/bmad-quick-dev-new-preview/steps/step-04-review.md +++ b/src/bmm/workflows/bmad-quick-flow/bmad-quick-dev-new-preview/steps/step-04-review.md @@ -2,7 +2,7 @@ name: 'step-04-review' description: 'Adversarial review, classify findings, optional spec loop' -adversarial_review_task: '{project-root}/_bmad/core/tasks/review-adversarial-general.xml' +adversarial_review_task: '{project-root}/_bmad/core/tasks/bmad-review-adversarial-general/workflow.md' edge_case_hunter_task: '{project-root}/_bmad/core/tasks/review-edge-case-hunter.xml' deferred_work_file: '{implementation_artifacts}/deferred-work.md' specLoopIteration: 1 diff --git a/src/bmm/workflows/bmad-quick-flow/bmad-quick-dev-new-preview/workflow.md b/src/bmm/workflows/bmad-quick-flow/bmad-quick-dev-new-preview/workflow.md index eae636173..a05e42efd 100644 --- a/src/bmm/workflows/bmad-quick-flow/bmad-quick-dev-new-preview/workflow.md +++ b/src/bmm/workflows/bmad-quick-flow/bmad-quick-dev-new-preview/workflow.md @@ -8,7 +8,7 @@ advanced_elicitation: '{project-root}/_bmad/core/workflows/advanced-elicitation/ party_mode_exec: '{project-root}/_bmad/core/workflows/party-mode/workflow.md' # Review building block -adversarial_review_task: '{project-root}/_bmad/core/tasks/review-adversarial-general.xml' +adversarial_review_task: '{project-root}/_bmad/core/tasks/bmad-review-adversarial-general/workflow.md' --- # Quick Dev New Preview Workflow diff --git a/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-05-adversarial-review.md b/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-05-adversarial-review.md index 8bbd6761e..457dbfd03 100644 --- a/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-05-adversarial-review.md +++ b/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-05-adversarial-review.md @@ -60,7 +60,7 @@ Merge all changes into `{diff_output}`. With `{diff_output}` constructed, load and follow the review task. If possible, use information asymmetry: load this step, and only it, in a separate subagent or process with read access to the project, but no context except the `{diff_output}`. ```xml -Review {diff_output} using {project-root}/_bmad/core/tasks/review-adversarial-general.xml +Review {diff_output} using {project-root}/_bmad/core/tasks/bmad-review-adversarial-general/workflow.md ``` **Platform fallback:** If task invocation not available, load the task file and follow its instructions inline, passing `{diff_output}` as the content. diff --git a/src/bmm/workflows/bmad-quick-flow/quick-spec/steps/step-04-review.md b/src/bmm/workflows/bmad-quick-flow/quick-spec/steps/step-04-review.md index 24c65d088..304802a23 100644 --- a/src/bmm/workflows/bmad-quick-flow/quick-spec/steps/step-04-review.md +++ b/src/bmm/workflows/bmad-quick-flow/quick-spec/steps/step-04-review.md @@ -153,7 +153,7 @@ b) **HALT and wait for user selection.** 1. **Invoke Adversarial Review Task**: > With `{finalFile}` constructed, load and follow the review task. If possible, use information asymmetry: load this task, and only it, in a separate subagent or process with read access to the project, but no context except the `{finalFile}`. - Review {finalFile} using {project-root}/_bmad/core/tasks/review-adversarial-general.xml + Review {finalFile} using {project-root}/_bmad/core/tasks/bmad-review-adversarial-general/workflow.md > **Platform fallback:** If task invocation not available, load the task file and follow its instructions inline, passing `{finalFile}` as the content. > The task should: review `{finalFile}` and return a list of findings. diff --git a/src/core/module-help.csv b/src/core/module-help.csv index 2e4419599..a56f33772 100644 --- a/src/core/module-help.csv +++ b/src/core/module-help.csv @@ -6,5 +6,5 @@ core,anytime,Index Docs,ID,,_bmad/core/tasks/index-docs.xml,bmad-index-docs,fals core,anytime,Shard Document,SD,,_bmad/core/tasks/shard-doc.xml,bmad-shard-doc,false,,,"Split large documents into smaller files by sections. Use when doc becomes too large (>500 lines) to manage effectively.",, core,anytime,Editorial Review - Prose,EP,,_bmad/core/tasks/editorial-review-prose.xml,bmad-editorial-review-prose,false,,,"Review prose for clarity, tone, and communication issues. Use after drafting to polish written content.",report located with target document,"three-column markdown table with suggested fixes", core,anytime,Editorial Review - Structure,ES,,_bmad/core/tasks/editorial-review-structure.xml,bmad-editorial-review-structure,false,,,"Propose cuts, reorganization, and simplification while preserving comprehension. Use when doc produced from multiple subprocesses or needs structural improvement.",report located with target document, -core,anytime,Adversarial Review (General),AR,,_bmad/core/tasks/review-adversarial-general.xml,bmad-review-adversarial-general,false,,,"Review content critically to find issues and weaknesses. Use for quality assurance or before finalizing deliverables. Code Review in other modules run this automatically, but its useful also for document reviews",, +core,anytime,Adversarial Review (General),AR,,skill:bmad-review-adversarial-general,bmad-review-adversarial-general,false,,,"Review content critically to find issues and weaknesses. Use for quality assurance or before finalizing deliverables. Code Review in other modules run this automatically, but its useful also for document reviews",, core,anytime,Edge Case Hunter Review,ECH,,_bmad/core/tasks/review-edge-case-hunter.xml,bmad-review-edge-case-hunter,false,,,"Walk every branching path and boundary condition in code, report only unhandled edge cases. Use alongside adversarial review for orthogonal coverage - method-driven not attitude-driven.",, diff --git a/src/core/tasks/bmad-review-adversarial-general/bmad-skill-manifest.yaml b/src/core/tasks/bmad-review-adversarial-general/bmad-skill-manifest.yaml new file mode 100644 index 000000000..d0f08abdb --- /dev/null +++ b/src/core/tasks/bmad-review-adversarial-general/bmad-skill-manifest.yaml @@ -0,0 +1 @@ +type: skill diff --git a/src/core/tasks/bmad-review-adversarial-general/workflow.md b/src/core/tasks/bmad-review-adversarial-general/workflow.md new file mode 100644 index 000000000..ae75b7caa --- /dev/null +++ b/src/core/tasks/bmad-review-adversarial-general/workflow.md @@ -0,0 +1,37 @@ +--- +name: bmad-review-adversarial-general +description: 'Perform a Cynical Review and produce a findings report. Use when the user requests a critical review of something' +--- + +# Adversarial Review (General) + +**Goal:** Cynically review content and produce findings. + +**Your Role:** You are a cynical, jaded reviewer with zero patience for sloppy work. The content was submitted by a clueless weasel and you expect to find problems. Be skeptical of everything. Look for what's missing, not just what's wrong. Use a precise, professional tone — no profanity or personal attacks. + +**Inputs:** +- **content** — Content to review: diff, spec, story, doc, or any artifact +- **also_consider** (optional) — Areas to keep in mind during review alongside normal adversarial analysis + + +## EXECUTION + +### Step 1: Receive Content + +- Load the content to review from provided input or context +- If content to review is empty, ask for clarification and abort +- Identify content type (diff, branch, uncommitted changes, document, etc.) + +### Step 2: Adversarial Analysis + +Review with extreme skepticism — assume problems exist. Find at least ten issues to fix or improve in the provided content. + +### Step 3: Present Findings + +Output findings as a Markdown list (descriptions only). + + +## HALT CONDITIONS + +- HALT if zero findings — this is suspicious, re-analyze or ask for guidance +- HALT if content is empty or unreadable diff --git a/src/core/tasks/bmad-skill-manifest.yaml b/src/core/tasks/bmad-skill-manifest.yaml index 4f7e6b40e..cfe67caa5 100644 --- a/src/core/tasks/bmad-skill-manifest.yaml +++ b/src/core/tasks/bmad-skill-manifest.yaml @@ -18,11 +18,6 @@ index-docs.xml: type: task description: "Generates or updates an index.md to reference all docs in the folder" -review-adversarial-general.xml: - canonicalId: bmad-review-adversarial-general - type: task - description: "Perform a Cynical Review and produce a findings report" - review-edge-case-hunter.xml: canonicalId: bmad-review-edge-case-hunter type: task diff --git a/src/core/tasks/review-adversarial-general.xml b/src/core/tasks/review-adversarial-general.xml deleted file mode 100644 index 58551aa60..000000000 --- a/src/core/tasks/review-adversarial-general.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - Cynically review content and produce findings - - - - - - - - MANDATORY: Execute ALL steps in the flow section IN EXACT ORDER - DO NOT skip steps or change the sequence - HALT immediately when halt-conditions are met - Each action xml tag within step xml tag is a REQUIRED action to complete that step - - You are a cynical, jaded reviewer with zero patience for sloppy work - The content was submitted by a clueless weasel and you expect to find problems - Be skeptical of everything - Look for what's missing, not just what's wrong - Use a precise, professional tone - no profanity or personal attacks - - - - - Load the content to review from provided input or context - If content to review is empty, ask for clarification and abort task - Identify content type (diff, branch, uncommitted changes, document, etc.) - - - - Review with extreme skepticism - assume problems exist - Find at least ten issues to fix or improve in the provided content - - - - Output findings as a Markdown list (descriptions only) - - - - - HALT if zero findings - this is suspicious, re-analyze or ask for guidance - HALT if content is empty or unreadable - - - \ No newline at end of file diff --git a/tools/cli/installers/lib/core/manifest-generator.js b/tools/cli/installers/lib/core/manifest-generator.js index 34a8fbbb4..c3a67faf8 100644 --- a/tools/cli/installers/lib/core/manifest-generator.js +++ b/tools/cli/installers/lib/core/manifest-generator.js @@ -444,11 +444,50 @@ class ManifestGenerator { */ async getTasksFromDir(dirPath, moduleName) { const tasks = []; - const files = await fs.readdir(dirPath); + const entries = await fs.readdir(dirPath, { withFileTypes: true }); // Load skill manifest for this directory (if present) const skillManifest = await this.loadSkillManifest(dirPath); - for (const file of files) { + for (const entry of entries) { + const fullPath = path.join(dirPath, entry.name); + + // Recurse into subdirectories (supports type:skill task directories) + if (entry.isDirectory()) { + const subManifest = await this.loadSkillManifest(fullPath); + const subArtifactType = this.getArtifactType(subManifest, 'workflow.md'); + + if (subArtifactType === 'skill') { + // This subdirectory is a type:skill — process its workflow.md + const workflowPath = path.join(fullPath, 'workflow.md'); + if (await fs.pathExists(workflowPath)) { + const content = await fs.readFile(workflowPath, 'utf8'); + const frontmatterMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---/); + if (frontmatterMatch) { + const frontmatter = yaml.parse(frontmatterMatch[1]); + if (frontmatter?.name && frontmatter?.description) { + const canonicalId = path.basename(fullPath); + const installPath = + moduleName === 'core' + ? `${this.bmadFolderName}/core/tasks/${entry.name}/workflow.md` + : `${this.bmadFolderName}/${moduleName}/tasks/${entry.name}/workflow.md`; + + this.skills.push({ + name: frontmatter.name, + description: this.cleanForCSV(frontmatter.description), + module: moduleName, + path: installPath, + canonicalId, + install_to_bmad: this.getInstallToBmad(subManifest, 'workflow.md'), + }); + } + } + } + } + continue; + } + + const file = entry.name; + // Check for both .xml and .md files if (file.endsWith('.xml') || file.endsWith('.md')) { const filePath = path.join(dirPath, file);