Skip to content

Commit ff711c1

Browse files
oalanicolasclaudePedrovaleriolopez
authored
feat: standardize workflow.sequence and CI improvements (#578)
* docs: rebrand to AIOX Squad with new tagline and domain - Rename from "Synkra AIOX" to "AIOX Squad: Artificial Intelligence Orchestration eXperience" - Update documentation URLs from synkra.ai to aioxsquad.ai - Add new tagline: "Giving people back the power to create" - Remove standalone BMad acknowledgment section (attribution preserved in Contributors) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(docs): address CodeRabbit review findings on README rebrand - Fix MD028 blockquote spacing in README.md - Correct agent count from 11 to 12 in README.md - Remove standalone Acknowledgments sections from both READMEs - Consolidate attribution under Contributors section Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * ci: replace CodeQL default setup with explicit workflow - Add .github/workflows/codeql.yml with javascript-typescript and actions only - Remove Python language (no Python source in repo) - Fixes stale working directory path from aios→aiox rename - Disable GitHub default CodeQL setup in favor of workflow file Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * standardize workflow.sequence across validator, templates, and docs * chore: sync entity registry with enriched metadata Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: address CodeRabbit review findings on PR #578 - Fix shallow copy mutation in workflow-validator.js _normalizeWorkflowDocument - Fix workflow_end YAML structure in example-workflow and workflow-template - Add missing data-engineer and devops agents to README.md agent list - Add language specifiers to fenced code blocks in create-workflow.md Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: Pedro Valerio <pedro@allfluence.com.br>
1 parent fcfb757 commit ff711c1

File tree

11 files changed

+521
-299
lines changed

11 files changed

+521
-299
lines changed

.aiox-core/development/scripts/workflow-validator.js

Lines changed: 92 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -101,36 +101,38 @@ class WorkflowValidator {
101101
return result; // Can't continue without parsed data
102102
}
103103

104-
const workflow = parseResult.data;
104+
const workflow = this._normalizeWorkflowDocument(parseResult.data);
105105

106106
// 3. Required fields
107107
const fieldsResult = this.validateRequiredFields(workflow, workflowPath);
108108
this._mergeResults(result, fieldsResult);
109109

110+
const phaseSequence = this._getPhaseSequence(workflow);
111+
110112
// 4. Phase sequence
111-
if (workflow.workflow && workflow.workflow.sequence) {
112-
const sequenceResult = this.validatePhaseSequence(workflow.workflow.sequence);
113+
if (phaseSequence.length > 0) {
114+
const sequenceResult = this.validatePhaseSequence(phaseSequence);
113115
this._mergeResults(result, sequenceResult);
114116

115117
// 5. Agent references
116-
const agentResult = await this.validateAgentReferences(workflow.workflow.sequence);
118+
const agentResult = await this.validateAgentReferences(phaseSequence);
117119
this._mergeResults(result, agentResult);
118120

119121
// 6. Artifact flow
120-
const artifactResult = this.validateArtifactFlow(workflow.workflow.sequence);
122+
const artifactResult = this.validateArtifactFlow(phaseSequence);
121123
this._mergeResults(result, artifactResult);
122124

123125
// 7. Circular dependencies
124-
const circularResult = this.detectCircularDeps(workflow.workflow.sequence);
126+
const circularResult = this.detectCircularDeps(phaseSequence);
125127
this._mergeResults(result, circularResult);
126128

127129
// 8. Conditional logic
128-
const conditionalResult = this.validateConditionalLogic(workflow.workflow.sequence);
130+
const conditionalResult = this.validateConditionalLogic(phaseSequence);
129131
this._mergeResults(result, conditionalResult);
130132
}
131133

132134
// 9. Handoff prompts
133-
const handoffResult = this.validateHandoffPrompts(workflow);
135+
const handoffResult = this.validateHandoffPrompts(workflow, phaseSequence);
134136
this._mergeResults(result, handoffResult);
135137

136138
// 10. Mermaid diagram
@@ -191,18 +193,18 @@ class WorkflowValidator {
191193
const result = { valid: true, errors: [], warnings: [], suggestions: [] };
192194
const filename = path.basename(filePath);
193195

194-
if (!workflow.workflow) {
196+
const wf = workflow.workflow;
197+
if (!wf || typeof wf !== 'object') {
195198
result.valid = false;
196199
result.errors.push({
197200
code: WorkflowValidationErrorCodes.WF_MISSING_REQUIRED_FIELD,
198-
message: 'Missing top-level "workflow:" key',
201+
message: 'Missing workflow payload (expected workflow.id, workflow.name, and sequence/phases)',
199202
file: filename,
200-
suggestion: 'Add workflow: as the root key containing id, name, and sequence',
203+
suggestion: 'Add workflow: root key or canonical top-level id/name/sequence|phases',
201204
});
202205
return result;
203206
}
204207

205-
const wf = workflow.workflow;
206208
const requiredFields = ['id', 'name'];
207209

208210
for (const field of requiredFields) {
@@ -217,13 +219,22 @@ class WorkflowValidator {
217219
}
218220
}
219221

220-
if (!wf.sequence || !Array.isArray(wf.sequence) || wf.sequence.length === 0) {
222+
const hasSequence = Array.isArray(wf.sequence) && wf.sequence.length > 0;
223+
const hasPhases = Array.isArray(wf.phases) && wf.phases.length > 0;
224+
if (!hasSequence && !hasPhases) {
221225
result.valid = false;
222226
result.errors.push({
223227
code: WorkflowValidationErrorCodes.WF_MISSING_REQUIRED_FIELD,
224-
message: 'Missing or empty "sequence:" array',
228+
message: 'Missing or empty workflow execution array ("sequence" or "phases")',
229+
file: filename,
230+
suggestion: 'Add workflow.sequence (official) with at least one step; phases is compatibility only',
231+
});
232+
} else if (!hasSequence && hasPhases) {
233+
result.warnings.push({
234+
code: WorkflowValidationErrorCodes.WF_MISSING_REQUIRED_FIELD,
235+
message: 'Workflow uses workflow.phases without workflow.sequence',
225236
file: filename,
226-
suggestion: 'Add sequence: with at least one step entry containing agent and creates/action',
237+
suggestion: 'Prefer workflow.sequence as canonical execution contract (keep phases only as supplemental metadata)',
227238
});
228239
}
229240

@@ -539,18 +550,20 @@ class WorkflowValidator {
539550
/**
540551
* Validate handoff prompts exist for transitions
541552
* @param {Object} workflow - Full parsed workflow
553+
* @param {Array|null} phaseSequence - Optional resolved phase sequence
542554
* @returns {Object} Validation result
543555
*/
544-
validateHandoffPrompts(workflow) {
556+
validateHandoffPrompts(workflow, phaseSequence = null) {
545557
const result = { valid: true, errors: [], warnings: [], suggestions: [] };
546558

547559
const wf = workflow.workflow;
548-
if (!wf || !wf.sequence || !Array.isArray(wf.sequence)) return result;
560+
const sequence = Array.isArray(phaseSequence) ? phaseSequence : this._getPhaseSequence(workflow);
561+
if (!wf || !Array.isArray(sequence) || sequence.length === 0) return result;
549562

550563
// Count agent transitions (where one agent hands off to another)
551564
let transitionCount = 0;
552565
let prevAgent = null;
553-
for (const step of wf.sequence) {
566+
for (const step of sequence) {
554567
if (step.agent && step.agent !== prevAgent) {
555568
if (prevAgent) transitionCount++;
556569
prevAgent = step.agent;
@@ -687,6 +700,67 @@ class WorkflowValidator {
687700
target.valid = false;
688701
}
689702
}
703+
704+
/**
705+
* Normalize workflow payload to keep backward compatibility across
706+
* workflow-wrapped and top-level workflow documents.
707+
* @private
708+
* @param {Object} data
709+
* @returns {Object}
710+
*/
711+
_normalizeWorkflowDocument(data) {
712+
if (!data || typeof data !== 'object') {
713+
return { workflow: null };
714+
}
715+
716+
if (data.workflow && typeof data.workflow === 'object') {
717+
const normalizedWorkflow = { ...data.workflow };
718+
if (!normalizedWorkflow.phases && Array.isArray(data.phases)) {
719+
normalizedWorkflow.phases = data.phases;
720+
}
721+
return { ...data, workflow: normalizedWorkflow };
722+
}
723+
724+
const normalizedWorkflow = {
725+
id: data.id,
726+
name: data.name,
727+
version: data.version,
728+
description: data.description,
729+
type: data.type,
730+
orchestrator: data.orchestrator,
731+
sequence: Array.isArray(data.sequence) ? data.sequence : undefined,
732+
phases: Array.isArray(data.phases) ? data.phases : undefined,
733+
handoff_prompts: data.handoff_prompts,
734+
flow_diagram: data.flow_diagram,
735+
};
736+
737+
return {
738+
...data,
739+
workflow: normalizedWorkflow,
740+
};
741+
}
742+
743+
/**
744+
* Resolve executable entries from canonical workflow.sequence[], with
745+
* workflow.phases[] as compatibility fallback.
746+
* @private
747+
* @param {Object} workflow
748+
* @returns {Array}
749+
*/
750+
_getPhaseSequence(workflow) {
751+
const wf = workflow && workflow.workflow ? workflow.workflow : null;
752+
if (!wf) return [];
753+
754+
if (Array.isArray(wf.sequence) && wf.sequence.length > 0) {
755+
return wf.sequence;
756+
}
757+
758+
if (Array.isArray(wf.phases) && wf.phases.length > 0) {
759+
return wf.phases;
760+
}
761+
762+
return [];
763+
}
690764
}
691765

692766
module.exports = {

.aiox-core/development/tasks/create-workflow.md

Lines changed: 44 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -273,23 +273,23 @@ ELICIT: Workflow Basic Information
273273
4. What is the expected outcome?
274274
```
275275

276-
### Step 2: Workflow Stages
277-
```
278-
ELICIT: Workflow Stages and Flow
279-
1. What are the main stages/phases? (e.g., "planning", "implementation", "testing")
280-
2. What is the sequence of these stages?
276+
### Step 2: Workflow Sequence Design
277+
```text
278+
ELICIT: Workflow Sequence and Flow
279+
1. What are the main execution steps/phases? (e.g., "planning", "implementation", "testing")
280+
2. What is the exact step order (`workflow.sequence`)?
281281
3. Are there any parallel activities?
282282
4. Are there decision points or conditional flows?
283-
5. What are the exit criteria for each stage?
283+
5. What are the exit criteria for each step?
284284
```
285285

286286
### Step 3: Agent Orchestration
287-
```
287+
```text
288288
ELICIT: Agent Participation
289-
For each stage:
289+
For each workflow step:
290290
1. Which agent(s) are involved?
291291
2. What are their specific responsibilities?
292-
3. How do agents hand off work between stages?
292+
3. How do agents hand off work between steps?
293293
4. Are there any approval requirements?
294294
```
295295

@@ -316,39 +316,41 @@ ELICIT: Resources and Dependencies
316316
workflow:
317317
id: {workflow-name}
318318
name: {Workflow Display Name}
319+
version: {semver}
319320
description: {Purpose and overview}
320321
type: {greenfield|brownfield}
321322
scope: {ui|service|fullstack}
322-
323-
stages:
324-
- id: stage-1
325-
name: {Stage Name}
326-
agent: {agent-id}
327-
tasks:
328-
- {task-name}
329-
outputs:
330-
- {output-description}
331-
next: stage-2
332-
333-
transitions:
334-
- from: stage-1
335-
to: stage-2
336-
condition: {optional condition}
337-
338-
resources:
339-
templates:
340-
- {template-name}
341-
data:
342-
- {data-file}
343-
344-
validation:
345-
checkpoints:
346-
- stage: {stage-id}
347-
criteria: {validation-criteria}
323+
324+
# Optional compatibility metadata (non-executable)
325+
phases:
326+
- phase_1: {phase label}
327+
- phase_2: {phase label}
328+
329+
# Canonical executable contract
330+
sequence:
331+
- step: {step-slug}
332+
id: {step-id}
333+
phase: {1..N}
334+
phase_name: {Phase Display Name}
335+
agent: {agent-id}
336+
task: {task-name}
337+
action: {what happens}
338+
requires: {previous-step-id}
339+
outputs:
340+
- {artifact-name}
341+
next: {next-step-id}
342+
on_failure: {fallback-step-id}
343+
344+
- workflow_end:
345+
id: complete
346+
action: workflow_complete
347+
348+
handoff_prompts:
349+
{from}_to_{to}: {handoff guidance}
348350
```
349351

350352
3. **Add Security Controls**
351-
- Stage authorization requirements
353+
- Step authorization requirements
352354
- Data access restrictions
353355
- Audit logging points
354356
- Approval workflows
@@ -378,21 +380,21 @@ ELICIT: Resources and Dependencies
378380
timestamp: new Date().toISOString(),
379381
metadata: {
380382
type: workflowType,
381-
stages: stageList,
383+
sequence_steps: stepList,
382384
agents: involvedAgents
383385
}
384386
});
385387
```
386388

387389
6. **Generate Documentation**
388390
- Create workflow diagram (text-based)
389-
- Document each stage's purpose
391+
- Document each step's purpose
390392
- List all handoff points
391393
- Include troubleshooting guide
392394

393395
## Validation Checklist
394396
- [ ] Workflow name is unique and valid
395-
- [ ] All stages have clear purposes
397+
- [ ] All sequence steps have clear purposes
396398
- [ ] Agent assignments are valid
397399
- [ ] No circular dependencies
398400
- [ ] All resources exist
@@ -415,14 +417,14 @@ ELICIT: Resources and Dependencies
415417
(hybrid → squads/{squad_name}/workflows/{workflow-name}.yaml)
416418
📊 Workflow Summary:
417419
- Context: {target_context} {squad_name if applicable}
418-
- Stages: {stage-count}
420+
- Steps: {step-count}
419421
- Agents: {agent-list}
420422
- Type: {workflow-type}
421423
🚀 To use: Select workflow when starting new project
422424
```
423425

424426
## Workflow Execution Notes
425427
- Workflows are selected during project initialization
426-
- Each stage execution is logged in memory
428+
- Each step execution is logged in memory
427429
- Progress tracking available through memory queries
428-
- Agents automatically receive stage-specific context
430+
- Agents automatically receive step-specific context

.aiox-core/development/tasks/validate-workflow.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -190,8 +190,8 @@ acceptance-criteria:
190190
- **Recovery:** Show line/column of syntax error
191191
192192
3. **Error:** Missing Required Fields
193-
- **Cause:** Workflow missing workflow.id, workflow.name, or sequence
194-
- **Resolution:** Add missing fields to workflow YAML
193+
- **Cause:** Workflow missing workflow.id, workflow.name, or execution array
194+
- **Resolution:** Add `workflow.sequence` (official). `workflow.phases` is accepted for compatibility only.
195195
- **Recovery:** Show which fields are missing with examples
196196

197197
---

0 commit comments

Comments
 (0)