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
This commit is contained in:
parent
dc8293e5df
commit
f899efab11
|
|
@ -2,7 +2,7 @@
|
||||||
name: 'step-04-review'
|
name: 'step-04-review'
|
||||||
description: 'Adversarial review, classify findings, optional spec loop'
|
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'
|
edge_case_hunter_task: '{project-root}/_bmad/core/tasks/review-edge-case-hunter.xml'
|
||||||
deferred_work_file: '{implementation_artifacts}/deferred-work.md'
|
deferred_work_file: '{implementation_artifacts}/deferred-work.md'
|
||||||
specLoopIteration: 1
|
specLoopIteration: 1
|
||||||
|
|
|
||||||
|
|
@ -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'
|
party_mode_exec: '{project-root}/_bmad/core/workflows/party-mode/workflow.md'
|
||||||
|
|
||||||
# Review building block
|
# 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
|
# Quick Dev New Preview Workflow
|
||||||
|
|
|
||||||
|
|
@ -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}`.
|
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
|
```xml
|
||||||
<invoke-task>Review {diff_output} using {project-root}/_bmad/core/tasks/review-adversarial-general.xml</invoke-task>
|
<invoke-task>Review {diff_output} using {project-root}/_bmad/core/tasks/bmad-review-adversarial-general/workflow.md</invoke-task>
|
||||||
```
|
```
|
||||||
|
|
||||||
**Platform fallback:** If task invocation not available, load the task file and follow its instructions inline, passing `{diff_output}` as the content.
|
**Platform fallback:** If task invocation not available, load the task file and follow its instructions inline, passing `{diff_output}` as the content.
|
||||||
|
|
|
||||||
|
|
@ -153,7 +153,7 @@ b) **HALT and wait for user selection.**
|
||||||
|
|
||||||
1. **Invoke Adversarial Review Task**:
|
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}`.
|
> 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}`.
|
||||||
<invoke-task>Review {finalFile} using {project-root}/_bmad/core/tasks/review-adversarial-general.xml</invoke-task>
|
<invoke-task>Review {finalFile} using {project-root}/_bmad/core/tasks/bmad-review-adversarial-general/workflow.md</invoke-task>
|
||||||
> **Platform fallback:** If task invocation not available, load the task file and follow its instructions inline, passing `{finalFile}` as the content.
|
> **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.
|
> The task should: review `{finalFile}` and return a list of findings.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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,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 - 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,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.",,
|
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.",,
|
||||||
|
|
|
||||||
|
Can't render this file because it has a wrong number of fields in line 2.
|
|
|
@ -0,0 +1 @@
|
||||||
|
type: skill
|
||||||
|
|
@ -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
|
||||||
|
|
@ -18,11 +18,6 @@ index-docs.xml:
|
||||||
type: task
|
type: task
|
||||||
description: "Generates or updates an index.md to reference all docs in the folder"
|
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:
|
review-edge-case-hunter.xml:
|
||||||
canonicalId: bmad-review-edge-case-hunter
|
canonicalId: bmad-review-edge-case-hunter
|
||||||
type: task
|
type: task
|
||||||
|
|
|
||||||
|
|
@ -1,49 +0,0 @@
|
||||||
<!-- if possible, run this in a separate subagent or process with read access to the project,
|
|
||||||
but no context except the content to review -->
|
|
||||||
|
|
||||||
<task id="_bmad/core/tasks/review-adversarial-general.xml" name="Adversarial Review (General)"
|
|
||||||
description="Perform a Cynical Review and produce a findings report. Use when the user requests a critical review of something">
|
|
||||||
<objective>Cynically review content and produce findings</objective>
|
|
||||||
|
|
||||||
<inputs>
|
|
||||||
<input name="content" desc="Content to review - diff, spec, story, doc, or any artifact" />
|
|
||||||
<input name="also_consider" required="false"
|
|
||||||
desc="Optional areas to keep in mind during review alongside normal adversarial analysis" />
|
|
||||||
</inputs>
|
|
||||||
|
|
||||||
<llm critical="true">
|
|
||||||
<i>MANDATORY: Execute ALL steps in the flow section IN EXACT ORDER</i>
|
|
||||||
<i>DO NOT skip steps or change the sequence</i>
|
|
||||||
<i>HALT immediately when halt-conditions are met</i>
|
|
||||||
<i>Each action xml tag within step xml tag is a REQUIRED action to complete that step</i>
|
|
||||||
|
|
||||||
<i>You are a cynical, jaded reviewer with zero patience for sloppy work</i>
|
|
||||||
<i>The content was submitted by a clueless weasel and you expect to find problems</i>
|
|
||||||
<i>Be skeptical of everything</i>
|
|
||||||
<i>Look for what's missing, not just what's wrong</i>
|
|
||||||
<i>Use a precise, professional tone - no profanity or personal attacks</i>
|
|
||||||
</llm>
|
|
||||||
|
|
||||||
<flow>
|
|
||||||
<step n="1" title="Receive Content">
|
|
||||||
<action>Load the content to review from provided input or context</action>
|
|
||||||
<action>If content to review is empty, ask for clarification and abort task</action>
|
|
||||||
<action>Identify content type (diff, branch, uncommitted changes, document, etc.)</action>
|
|
||||||
</step>
|
|
||||||
|
|
||||||
<step n="2" title="Adversarial Analysis" critical="true">
|
|
||||||
<mandate>Review with extreme skepticism - assume problems exist</mandate>
|
|
||||||
<action>Find at least ten issues to fix or improve in the provided content</action>
|
|
||||||
</step>
|
|
||||||
|
|
||||||
<step n="3" title="Present Findings">
|
|
||||||
<action>Output findings as a Markdown list (descriptions only)</action>
|
|
||||||
</step>
|
|
||||||
</flow>
|
|
||||||
|
|
||||||
<halt-conditions>
|
|
||||||
<condition>HALT if zero findings - this is suspicious, re-analyze or ask for guidance</condition>
|
|
||||||
<condition>HALT if content is empty or unreadable</condition>
|
|
||||||
</halt-conditions>
|
|
||||||
|
|
||||||
</task>
|
|
||||||
|
|
@ -444,11 +444,50 @@ class ManifestGenerator {
|
||||||
*/
|
*/
|
||||||
async getTasksFromDir(dirPath, moduleName) {
|
async getTasksFromDir(dirPath, moduleName) {
|
||||||
const tasks = [];
|
const tasks = [];
|
||||||
const files = await fs.readdir(dirPath);
|
const entries = await fs.readdir(dirPath, { withFileTypes: true });
|
||||||
// Load skill manifest for this directory (if present)
|
// Load skill manifest for this directory (if present)
|
||||||
const skillManifest = await this.loadSkillManifest(dirPath);
|
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
|
// Check for both .xml and .md files
|
||||||
if (file.endsWith('.xml') || file.endsWith('.md')) {
|
if (file.endsWith('.xml') || file.endsWith('.md')) {
|
||||||
const filePath = path.join(dirPath, file);
|
const filePath = path.join(dirPath, file);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue