@jterrats/open-orchestra 1.0.3 → 1.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/autonomous-phase-lifecycle.js +19 -0
- package/dist/autonomous-phase-lifecycle.js.map +1 -1
- package/dist/autonomous-run-store.d.ts +2 -1
- package/dist/autonomous-run-store.js +4 -0
- package/dist/autonomous-run-store.js.map +1 -1
- package/dist/autonomous-workflow-constants.d.ts +1 -6
- package/dist/autonomous-workflow-constants.js +1 -33
- package/dist/autonomous-workflow-constants.js.map +1 -1
- package/dist/command-manifest.js +1 -1
- package/dist/command-manifest.js.map +1 -1
- package/dist/constants.d.ts +2 -4
- package/dist/constants.js +2 -21
- package/dist/constants.js.map +1 -1
- package/dist/defaults.d.ts +1 -0
- package/dist/defaults.js +1 -0
- package/dist/defaults.js.map +1 -1
- package/dist/delegation-decision.js +4 -5
- package/dist/delegation-decision.js.map +1 -1
- package/dist/delivery-dashboard.js +2 -1
- package/dist/delivery-dashboard.js.map +1 -1
- package/dist/phase-playbooks.js +32 -28
- package/dist/phase-playbooks.js.map +1 -1
- package/dist/qa-readiness.js +2 -2
- package/dist/qa-readiness.js.map +1 -1
- package/dist/release-readiness.js +3 -6
- package/dist/release-readiness.js.map +1 -1
- package/dist/runtime-execution.d.ts +10 -1
- package/dist/runtime-execution.js +118 -0
- package/dist/runtime-execution.js.map +1 -1
- package/dist/runtime-guardrails.js +1 -0
- package/dist/runtime-guardrails.js.map +1 -1
- package/dist/skills-catalog.js +135 -0
- package/dist/skills-catalog.js.map +1 -1
- package/dist/subagent-protocol.js +2 -1
- package/dist/subagent-protocol.js.map +1 -1
- package/dist/task-graph-commands.js +3 -12
- package/dist/task-graph-commands.js.map +1 -1
- package/dist/task-split-assessment.d.ts +19 -0
- package/dist/task-split-assessment.js +190 -0
- package/dist/task-split-assessment.js.map +1 -0
- package/dist/task-status.d.ts +22 -0
- package/dist/task-status.js +83 -0
- package/dist/task-status.js.map +1 -0
- package/dist/telemetry-records.js +2 -1
- package/dist/telemetry-records.js.map +1 -1
- package/dist/tracker-commands.js +2 -2
- package/dist/tracker-commands.js.map +1 -1
- package/dist/types/model-config.d.ts +2 -0
- package/dist/types/runtime.d.ts +1 -1
- package/dist/types/tasks.d.ts +1 -0
- package/dist/types/workflow-run.d.ts +15 -0
- package/dist/types.d.ts +1 -1
- package/dist/web-api.js +3 -2
- package/dist/web-api.js.map +1 -1
- package/dist/web-roles.js +2 -1
- package/dist/web-roles.js.map +1 -1
- package/dist/workflow-phase-planner.d.ts +4 -2
- package/dist/workflow-phase-planner.js +57 -38
- package/dist/workflow-phase-planner.js.map +1 -1
- package/dist/workflow-phases.d.ts +15 -0
- package/dist/workflow-phases.js +86 -0
- package/dist/workflow-phases.js.map +1 -0
- package/dist/workflow-run-commands.js +88 -2
- package/dist/workflow-run-commands.js.map +1 -1
- package/dist/workflow-services.js +4 -2
- package/dist/workflow-services.js.map +1 -1
- package/dist/workflow-task-service.js +2 -4
- package/dist/workflow-task-service.js.map +1 -1
- package/docs/autonomous-workflow.md +34 -0
- package/docs/backlog/chaos-testing-stack-strategy.md +146 -0
- package/docs/backlog/project-persona-registry-epic.md +350 -0
- package/docs/duplicate-code-enforcement.md +60 -0
- package/docs/release-test-matrix.md +14 -0
- package/docs/reports/duplicate-code-baseline-20260518.md +41 -0
- package/docs/runtime-adapters.md +44 -0
- package/docs/runtime-llm-flow.md +4 -2
- package/docs/secret-scanning-gitleaks.md +53 -0
- package/docs/site-manifest.json +5 -0
- package/docs/sonar-architecture-model.md +178 -0
- package/docs/sonar-quality-gates.md +178 -0
- package/docs/task-split-assessment.md +34 -0
- package/package.json +5 -1
- package/skills/chaos-resilience-testing/SKILL.md +127 -0
- package/skills/chaos-resilience-testing/manifest.json +61 -0
- package/skills/oclif-plugin-development/SKILL.md +118 -0
- package/skills/oclif-plugin-development/manifest.json +58 -0
|
@@ -1,19 +1,10 @@
|
|
|
1
|
-
import { AUTONOMOUS_PHASE_SEQUENCE } from "./
|
|
1
|
+
import { AUTONOMOUS_PHASE_SEQUENCE, OPTIONAL_WORKFLOW_PHASES, workflowPhaseById, workflowPhaseForRole, } from "./workflow-phases.js";
|
|
2
2
|
import { detectProjectProfile } from "./project-detection.js";
|
|
3
|
+
import { assessTaskSplit } from "./task-split-assessment.js";
|
|
4
|
+
import { taskSearchText } from "./task-text.js";
|
|
3
5
|
import { getWorkflowConfig } from "./workflow-services.js";
|
|
4
6
|
import { loadWorkspace } from "./workspace.js";
|
|
5
|
-
export const OPTIONAL_RECOMMENDED_PHASES =
|
|
6
|
-
{
|
|
7
|
-
phase: "ux_review",
|
|
8
|
-
role: "ux_ui_designer",
|
|
9
|
-
summary: "UX, accessibility, responsive behavior, and user-flow validation",
|
|
10
|
-
},
|
|
11
|
-
{
|
|
12
|
-
phase: "docs_review",
|
|
13
|
-
role: "technical_writer",
|
|
14
|
-
summary: "Documentation, public-site copy, changelog, and help-content review",
|
|
15
|
-
},
|
|
16
|
-
];
|
|
7
|
+
export const OPTIONAL_RECOMMENDED_PHASES = OPTIONAL_WORKFLOW_PHASES;
|
|
17
8
|
export async function recommendWorkflowPhasePlan(taskId, root = process.cwd()) {
|
|
18
9
|
const workspace = await loadWorkspace(root);
|
|
19
10
|
const task = workspace.tasks.find((candidate) => candidate.id === taskId);
|
|
@@ -26,6 +17,7 @@ export async function recommendWorkflowPhasePlan(taskId, root = process.cwd()) {
|
|
|
26
17
|
const configuredSequence = config.workflow?.phaseSequence ?? [];
|
|
27
18
|
const manualOverride = configuredSequence.length > 0;
|
|
28
19
|
const recommendations = recommendedPhases(task, profile.signals.map((s) => s.id));
|
|
20
|
+
const splitAssessment = assessTaskSplit(task);
|
|
29
21
|
const baseSequence = AUTONOMOUS_PHASE_SEQUENCE;
|
|
30
22
|
const taskPhaseSequence = task.workflow?.phaseSequence ?? [];
|
|
31
23
|
const taskOverride = taskPhaseSequence.length > 0;
|
|
@@ -41,7 +33,9 @@ export async function recommendWorkflowPhasePlan(taskId, root = process.cwd()) {
|
|
|
41
33
|
baseSequence,
|
|
42
34
|
recommendedSequence,
|
|
43
35
|
recommendations,
|
|
36
|
+
splitAssessment,
|
|
44
37
|
rationale: [
|
|
38
|
+
...splitAssessmentRationale(splitAssessment),
|
|
45
39
|
...((task.workflow?.requiredRoles ?? []).length > 0
|
|
46
40
|
? [
|
|
47
41
|
`Task declares required roles: ${task.workflow.requiredRoles.join(", ")}; matching phases are included when available.`,
|
|
@@ -67,18 +61,48 @@ export async function recommendWorkflowPhasePlan(taskId, root = process.cwd()) {
|
|
|
67
61
|
],
|
|
68
62
|
};
|
|
69
63
|
}
|
|
64
|
+
function splitAssessmentRationale(assessment) {
|
|
65
|
+
if (!assessment.shouldSplit) {
|
|
66
|
+
return [
|
|
67
|
+
"Task split assessment: no functional or technical oversize signals exceeded advisory thresholds.",
|
|
68
|
+
];
|
|
69
|
+
}
|
|
70
|
+
const lines = [
|
|
71
|
+
"Task split assessment: split recommended before implementation.",
|
|
72
|
+
];
|
|
73
|
+
if (assessment.functional.shouldSplit) {
|
|
74
|
+
lines.push(`PO/BA functional scope review: ${assessment.functional.findings.join(" ")}`);
|
|
75
|
+
}
|
|
76
|
+
if (assessment.technical.shouldSplit) {
|
|
77
|
+
lines.push(`Architect technical complexity review: ${assessment.technical.findings.join(" ")}`);
|
|
78
|
+
}
|
|
79
|
+
return lines;
|
|
80
|
+
}
|
|
70
81
|
function recommendedPhases(task, signalIds) {
|
|
71
82
|
const text = taskText(task);
|
|
72
83
|
const signals = new Set(signalIds);
|
|
73
84
|
const recommendations = [];
|
|
74
|
-
if (signals.has("frontend") &&
|
|
75
|
-
|
|
85
|
+
if (signals.has("frontend") && hasUserFacingUxSignal(task, text)) {
|
|
86
|
+
recommendations.push({
|
|
87
|
+
phase: "ux_design",
|
|
88
|
+
role: "ux_ui_designer",
|
|
89
|
+
summary: "UX design input, user-flow specification, responsive states, and accessibility criteria before architecture",
|
|
90
|
+
reason: "Frontend project signal plus task scope indicates UX, accessibility, or browser behavior risk that should inform architecture before implementation design.",
|
|
91
|
+
insertAfter: "po",
|
|
92
|
+
});
|
|
93
|
+
recommendations.push({
|
|
94
|
+
phase: "po_validation",
|
|
95
|
+
role: "product_owner",
|
|
96
|
+
summary: "Product and BA validation of UX artifacts before architecture commits to implementation design",
|
|
97
|
+
reason: "UX artifacts can change flow, layout, copy, states, or scope; Product/BA should validate them before architecture.",
|
|
98
|
+
insertAfter: "ux_design",
|
|
99
|
+
});
|
|
76
100
|
recommendations.push({
|
|
77
101
|
phase: "ux_review",
|
|
78
102
|
role: "ux_ui_designer",
|
|
79
103
|
summary: "UX, accessibility, responsive behavior, and user-flow validation",
|
|
80
|
-
reason: "Frontend project signal plus task scope indicates UX, accessibility, or browser behavior risk.",
|
|
81
|
-
insertAfter: "
|
|
104
|
+
reason: "Frontend project signal plus task scope indicates UX, accessibility, or browser behavior risk that needs post-implementation validation.",
|
|
105
|
+
insertAfter: "qa",
|
|
82
106
|
});
|
|
83
107
|
}
|
|
84
108
|
if (/\b(docs?|documentation|readme|changelog|runbook|public site|site copy|help content)\b/i.test(text) ||
|
|
@@ -116,15 +140,19 @@ function applyRecommendations(baseSequence, recommendations) {
|
|
|
116
140
|
function applyRequiredRoles(sequence, requiredRoles) {
|
|
117
141
|
if (requiredRoles.length === 0)
|
|
118
142
|
return sequence;
|
|
119
|
-
const phaseByRole = new Map([...AUTONOMOUS_PHASE_SEQUENCE, ...OPTIONAL_RECOMMENDED_PHASES].map((phase) => [phase.role, phase]));
|
|
120
143
|
let next = [...sequence];
|
|
121
144
|
for (const role of requiredRoles) {
|
|
122
145
|
if (next.some((phase) => phase.role === role))
|
|
123
146
|
continue;
|
|
124
|
-
const
|
|
147
|
+
const defaultPhase = workflowPhaseForRole(role);
|
|
148
|
+
const phase = defaultPhase ? workflowPhaseById(defaultPhase) : undefined;
|
|
125
149
|
if (!phase)
|
|
126
150
|
continue;
|
|
127
|
-
const insertAfter = phase.phase === "docs_review"
|
|
151
|
+
const insertAfter = phase.phase === "docs_review"
|
|
152
|
+
? "qa"
|
|
153
|
+
: phase.phase === "ux_design"
|
|
154
|
+
? "po"
|
|
155
|
+
: "developer";
|
|
128
156
|
next = applyRecommendations(next, [
|
|
129
157
|
{
|
|
130
158
|
phase: phase.phase,
|
|
@@ -137,13 +165,12 @@ function applyRequiredRoles(sequence, requiredRoles) {
|
|
|
137
165
|
}
|
|
138
166
|
return next;
|
|
139
167
|
}
|
|
168
|
+
function hasUserFacingUxSignal(task, text) {
|
|
169
|
+
return (/\b(ui|ux|frontend|responsive|mobile|accessibility|browser|site|web|navigation|layout|form|forms|table|tables|dashboard|filter|filters|pagination|copy|tooltip|tooltips|loading|empty|error|success|recovery|visual)\b/i.test(text) ||
|
|
170
|
+
(task.paths ?? []).some((item) => /(^|\/)(site|web-console)\/src\/|\.jsx$|\.css$/i.test(item)));
|
|
171
|
+
}
|
|
140
172
|
function sequenceFromIds(ids) {
|
|
141
|
-
|
|
142
|
-
...AUTONOMOUS_PHASE_SEQUENCE,
|
|
143
|
-
...OPTIONAL_RECOMMENDED_PHASES,
|
|
144
|
-
];
|
|
145
|
-
const byId = new Map(definitions.map((phase) => [phase.phase, phase]));
|
|
146
|
-
return ids.map((id) => byId.get(id) ?? {
|
|
173
|
+
return ids.map((id) => workflowPhaseById(id) ?? {
|
|
147
174
|
phase: id,
|
|
148
175
|
role: "custom",
|
|
149
176
|
summary: "Custom configured workflow phase",
|
|
@@ -159,17 +186,9 @@ function dedupeRecommendations(recommendations) {
|
|
|
159
186
|
});
|
|
160
187
|
}
|
|
161
188
|
function taskText(task) {
|
|
162
|
-
return
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
task.testStrategy,
|
|
167
|
-
...(task.acceptanceCriteria ?? []),
|
|
168
|
-
...(task.assumptions ?? []),
|
|
169
|
-
...(task.risks ?? []),
|
|
170
|
-
...(task.paths ?? []),
|
|
171
|
-
]
|
|
172
|
-
.filter(Boolean)
|
|
173
|
-
.join(" ");
|
|
189
|
+
return taskSearchText(task, {
|
|
190
|
+
includeTestStrategy: true,
|
|
191
|
+
includeAssumptions: true,
|
|
192
|
+
});
|
|
174
193
|
}
|
|
175
194
|
//# sourceMappingURL=workflow-phase-planner.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workflow-phase-planner.js","sourceRoot":"","sources":["../src/workflow-phase-planner.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"workflow-phase-planner.js","sourceRoot":"","sources":["../src/workflow-phase-planner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface WorkflowPhaseDefinition {
|
|
2
|
+
phase: string;
|
|
3
|
+
role: string;
|
|
4
|
+
summary: string;
|
|
5
|
+
}
|
|
6
|
+
export declare const AUTONOMOUS_PHASE_SEQUENCE: WorkflowPhaseDefinition[];
|
|
7
|
+
export declare const OPTIONAL_WORKFLOW_PHASES: WorkflowPhaseDefinition[];
|
|
8
|
+
export declare const WORKFLOW_PHASES: WorkflowPhaseDefinition[];
|
|
9
|
+
export type AutonomousPhaseDefinition = (typeof AUTONOMOUS_PHASE_SEQUENCE)[number];
|
|
10
|
+
export declare function workflowPhaseById(phase: string): WorkflowPhaseDefinition | undefined;
|
|
11
|
+
export declare function isWorkflowPhase(phase: string): boolean;
|
|
12
|
+
export declare function workflowPhaseIds(): string[];
|
|
13
|
+
export declare function roleForWorkflowPhase(phase: string): string;
|
|
14
|
+
export declare function workflowPhaseForRole(role: string): string | undefined;
|
|
15
|
+
export declare function workflowPhasesByRole(role: string): WorkflowPhaseDefinition[];
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
export const AUTONOMOUS_PHASE_SEQUENCE = [
|
|
2
|
+
{
|
|
3
|
+
phase: "pm",
|
|
4
|
+
role: "product_manager",
|
|
5
|
+
summary: "Product framing, prioritization, and success metrics",
|
|
6
|
+
},
|
|
7
|
+
{
|
|
8
|
+
phase: "po",
|
|
9
|
+
role: "product_owner",
|
|
10
|
+
summary: "Backlog refinement, story sizing, and acceptance criteria",
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
phase: "architect",
|
|
14
|
+
role: "architect",
|
|
15
|
+
summary: "Technical tasking, design decisions, and size estimation",
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
phase: "developer",
|
|
19
|
+
role: "developer",
|
|
20
|
+
summary: "Implementation against acceptance criteria",
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
phase: "qa",
|
|
24
|
+
role: "qa",
|
|
25
|
+
summary: "Verification against acceptance criteria and edge cases",
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
phase: "release",
|
|
29
|
+
role: "release_manager",
|
|
30
|
+
summary: "Release candidate validation and PR creation",
|
|
31
|
+
},
|
|
32
|
+
];
|
|
33
|
+
export const OPTIONAL_WORKFLOW_PHASES = [
|
|
34
|
+
{
|
|
35
|
+
phase: "ux_design",
|
|
36
|
+
role: "ux_ui_designer",
|
|
37
|
+
summary: "UX design input, user-flow specification, responsive states, and accessibility criteria before architecture",
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
phase: "po_validation",
|
|
41
|
+
role: "product_owner",
|
|
42
|
+
summary: "Product and BA validation of UX artifacts before architecture commits to implementation design",
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
phase: "ux_review",
|
|
46
|
+
role: "ux_ui_designer",
|
|
47
|
+
summary: "UX, accessibility, responsive behavior, and user-flow validation",
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
phase: "docs_review",
|
|
51
|
+
role: "technical_writer",
|
|
52
|
+
summary: "Documentation, public-site copy, changelog, and help-content review",
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
phase: "architecture_challenge",
|
|
56
|
+
role: "reviewer_critic",
|
|
57
|
+
summary: "Architecture challenge for over-engineered, convention-breaking, or under-specified design",
|
|
58
|
+
},
|
|
59
|
+
];
|
|
60
|
+
export const WORKFLOW_PHASES = [
|
|
61
|
+
...AUTONOMOUS_PHASE_SEQUENCE,
|
|
62
|
+
...OPTIONAL_WORKFLOW_PHASES,
|
|
63
|
+
];
|
|
64
|
+
const PHASE_BY_ID = new Map(WORKFLOW_PHASES.map((definition) => [definition.phase, definition]));
|
|
65
|
+
const DEFAULT_PHASE_BY_ROLE = new Map(WORKFLOW_PHASES.map((definition) => [definition.role, definition.phase]));
|
|
66
|
+
DEFAULT_PHASE_BY_ROLE.set("product_owner", "po");
|
|
67
|
+
DEFAULT_PHASE_BY_ROLE.set("ux_ui_designer", "ux_review");
|
|
68
|
+
export function workflowPhaseById(phase) {
|
|
69
|
+
return PHASE_BY_ID.get(phase);
|
|
70
|
+
}
|
|
71
|
+
export function isWorkflowPhase(phase) {
|
|
72
|
+
return PHASE_BY_ID.has(phase);
|
|
73
|
+
}
|
|
74
|
+
export function workflowPhaseIds() {
|
|
75
|
+
return WORKFLOW_PHASES.map((definition) => definition.phase);
|
|
76
|
+
}
|
|
77
|
+
export function roleForWorkflowPhase(phase) {
|
|
78
|
+
return workflowPhaseById(phase)?.role ?? phase;
|
|
79
|
+
}
|
|
80
|
+
export function workflowPhaseForRole(role) {
|
|
81
|
+
return DEFAULT_PHASE_BY_ROLE.get(role);
|
|
82
|
+
}
|
|
83
|
+
export function workflowPhasesByRole(role) {
|
|
84
|
+
return WORKFLOW_PHASES.filter((definition) => definition.role === role);
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=workflow-phases.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow-phases.js","sourceRoot":"","sources":["../src/workflow-phases.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,12 +4,18 @@ import { numberOption, parseCsv, removeUndefined, stringOption, } from "./comman
|
|
|
4
4
|
import { AUTONOMOUS_PHASE_SEQUENCE, PHASE_GATES, autonomousRunsPath, cancelRun, checkArchitectSizing, closePhase, createAutonomousRun, initPhase, listActiveAutonomousRuns, listAutonomousRuns, markRunDone, markRunFailed, persistRun, readAutonomousRun, resumePhaseFromClarification, resumePhaseIndex, suspendPhaseForClarification, } from "./autonomous-workflow.js";
|
|
5
5
|
import { answerClarification, listClarifications, listClarificationsByTask, openClarification, resolveClarificationRole, } from "./clarification.js";
|
|
6
6
|
import { executePhaseWithLlm } from "./phase-executor.js";
|
|
7
|
+
import { planWorkflowPhaseExecutor } from "./runtime-execution.js";
|
|
7
8
|
import { addEvidence, applyProviderRuntimeProfile, approveWorkflowGate, generatePullRequestSummary, getWorkflowConfig, providerFailuresFromError, listTasks, } from "./workflow-services.js";
|
|
8
9
|
import { recommendWorkflowPhasePlan } from "./workflow-phase-planner.js";
|
|
9
10
|
import { OPTIONAL_RECOMMENDED_PHASES } from "./workflow-phase-planner.js";
|
|
10
11
|
import { buildPrBody, createPullRequest } from "./github.js";
|
|
11
12
|
const GATE_MODES = ["none", "phase", "all"];
|
|
12
13
|
const WORKFLOW_RUN_MODES = ["new", "redo", "sign-off"];
|
|
14
|
+
const WORKFLOW_PHASE_EXECUTION_MODES = [
|
|
15
|
+
"auto",
|
|
16
|
+
"subagents",
|
|
17
|
+
"single-agent",
|
|
18
|
+
];
|
|
13
19
|
export async function workflowRunCommand(options, io) {
|
|
14
20
|
await runWorkflowRun(options, io, process.cwd());
|
|
15
21
|
}
|
|
@@ -17,6 +23,7 @@ export async function runWorkflowRun(options, io, cwd = process.cwd()) {
|
|
|
17
23
|
const taskId = requireArg(options, "task");
|
|
18
24
|
const gates = (stringOption(options.gates) ?? "phase");
|
|
19
25
|
const mode = (stringOption(options.mode) ?? "new");
|
|
26
|
+
const requestedPhaseExecutionMode = stringOption(options["phase-execution"]);
|
|
20
27
|
const maxIterations = numberOption(options["max-iterations"], 5);
|
|
21
28
|
const timeoutMinutes = numberOption(options["timeout-minutes"], 0);
|
|
22
29
|
const file = autonomousRunsPath(cwd);
|
|
@@ -37,6 +44,7 @@ export async function runWorkflowRun(options, io, cwd = process.cwd()) {
|
|
|
37
44
|
}
|
|
38
45
|
const config = await getWorkflowConfig(cwd);
|
|
39
46
|
const phaseTimeoutMinutes = config.workflow?.phaseTimeoutMinutes ?? 0;
|
|
47
|
+
const phaseExecutionMode = resolvePhaseExecutionMode(requestedPhaseExecutionMode, config.workflow?.phaseExecutionMode);
|
|
40
48
|
if (!GATE_MODES.includes(gates)) {
|
|
41
49
|
throw new Error(`--gates must be one of: ${GATE_MODES.join(", ")}`);
|
|
42
50
|
}
|
|
@@ -50,7 +58,7 @@ export async function runWorkflowRun(options, io, cwd = process.cwd()) {
|
|
|
50
58
|
throw new Error("workflow.phaseTimeoutMinutes must be 0 or greater");
|
|
51
59
|
}
|
|
52
60
|
if (options["dry-run"]) {
|
|
53
|
-
return workflowDryRun(cwd, options, io, taskId, gates, maxIterations, phaseSelection);
|
|
61
|
+
return workflowDryRun(cwd, options, io, taskId, gates, maxIterations, phaseSelection, phaseExecutionMode);
|
|
54
62
|
}
|
|
55
63
|
let run;
|
|
56
64
|
let startIndex;
|
|
@@ -61,6 +69,7 @@ export async function runWorkflowRun(options, io, cwd = process.cwd()) {
|
|
|
61
69
|
}
|
|
62
70
|
run = existing;
|
|
63
71
|
run = { ...run, mode };
|
|
72
|
+
run = { ...run, phaseExecutionMode };
|
|
64
73
|
if (run.status === "canceled" || run.status === "failed") {
|
|
65
74
|
throw new Error(`workflow run ${run.id} is ${run.status} and cannot be resumed`);
|
|
66
75
|
}
|
|
@@ -92,12 +101,14 @@ export async function runWorkflowRun(options, io, cwd = process.cwd()) {
|
|
|
92
101
|
mode,
|
|
93
102
|
phaseSequence: phaseSelection.sequence.map((phase) => phase.phase),
|
|
94
103
|
phaseDefinitions: phaseSelection.sequence,
|
|
104
|
+
phaseExecutionMode,
|
|
95
105
|
skippedPhases: uniquePhases([
|
|
96
106
|
...phaseSelection.skipped,
|
|
97
107
|
...phaseSelection.sequence.slice(0, startIndex),
|
|
98
108
|
]),
|
|
99
109
|
});
|
|
100
110
|
io.log(`Started autonomous workflow ${run.id} for task ${taskId} [gates=${gates} mode=${mode}]`);
|
|
111
|
+
io.log(`Phase execution: ${phaseExecutionMode}`);
|
|
101
112
|
if (fromPhase) {
|
|
102
113
|
io.log(`Starting from phase ${fromPhase}`);
|
|
103
114
|
}
|
|
@@ -106,6 +117,7 @@ export async function runWorkflowRun(options, io, cwd = process.cwd()) {
|
|
|
106
117
|
runTimeoutMinutes: timeoutMinutes,
|
|
107
118
|
phaseTimeoutMinutes,
|
|
108
119
|
jsonOutput: Boolean(options.json),
|
|
120
|
+
phaseExecutionMode,
|
|
109
121
|
});
|
|
110
122
|
const result = { run, file, cwd };
|
|
111
123
|
if (options.json) {
|
|
@@ -380,6 +392,13 @@ function validateWorkflowPhaseSequence(sequence) {
|
|
|
380
392
|
throw new Error("workflow phase sequence must place developer before qa");
|
|
381
393
|
}
|
|
382
394
|
}
|
|
395
|
+
function resolvePhaseExecutionMode(requested, configured) {
|
|
396
|
+
const mode = requested ?? configured ?? "auto";
|
|
397
|
+
if (!WORKFLOW_PHASE_EXECUTION_MODES.includes(mode)) {
|
|
398
|
+
throw new Error(`--phase-execution must be one of: ${WORKFLOW_PHASE_EXECUTION_MODES.join(", ")}`);
|
|
399
|
+
}
|
|
400
|
+
return mode;
|
|
401
|
+
}
|
|
383
402
|
function phaseIndexForId(phaseId, sequence, source) {
|
|
384
403
|
const index = sequence.findIndex((phase) => phase.phase === phaseId);
|
|
385
404
|
if (index === -1) {
|
|
@@ -511,6 +530,46 @@ async function updatePhaseProviderProgress(root, run, phase, progress) {
|
|
|
511
530
|
await persistRun(root, updated);
|
|
512
531
|
return updated;
|
|
513
532
|
}
|
|
533
|
+
async function updatePhaseExecutorProvenance(root, run, phase, executor) {
|
|
534
|
+
const updated = {
|
|
535
|
+
...run,
|
|
536
|
+
updatedAt: new Date().toISOString(),
|
|
537
|
+
phases: run.phases.map((candidate) => candidate.phase === phase ? { ...candidate, executor } : candidate),
|
|
538
|
+
};
|
|
539
|
+
await persistRun(root, updated);
|
|
540
|
+
return updated;
|
|
541
|
+
}
|
|
542
|
+
async function pauseForQueuedPhaseExecutor(root, run, phase, input) {
|
|
543
|
+
const updatedAt = new Date().toISOString();
|
|
544
|
+
const updated = {
|
|
545
|
+
...run,
|
|
546
|
+
status: "paused",
|
|
547
|
+
updatedAt,
|
|
548
|
+
phases: run.phases.map((candidate) => candidate.phase === phase
|
|
549
|
+
? {
|
|
550
|
+
...candidate,
|
|
551
|
+
status: "blocked",
|
|
552
|
+
notes: input.reason,
|
|
553
|
+
completedAt: updatedAt,
|
|
554
|
+
}
|
|
555
|
+
: candidate),
|
|
556
|
+
};
|
|
557
|
+
await persistRun(root, updated);
|
|
558
|
+
await appendEvent(root, {
|
|
559
|
+
type: "WORKFLOW_PHASE_QUEUED",
|
|
560
|
+
taskId: run.taskId,
|
|
561
|
+
actor: "parent",
|
|
562
|
+
summary: `Workflow phase queued: ${phase}`,
|
|
563
|
+
artifacts: input.artifact ? [input.artifact] : [],
|
|
564
|
+
metadata: {
|
|
565
|
+
runId: run.id,
|
|
566
|
+
phase,
|
|
567
|
+
reason: input.reason,
|
|
568
|
+
resumeCommand: `orchestra workflow run --task ${run.taskId} --resume ${run.id}`,
|
|
569
|
+
},
|
|
570
|
+
});
|
|
571
|
+
return updated;
|
|
572
|
+
}
|
|
514
573
|
async function executePhases(cwd, run, startIndex, io, sequence, timeoutOptions) {
|
|
515
574
|
let current = run;
|
|
516
575
|
let qaFailNotes;
|
|
@@ -545,6 +604,31 @@ async function executePhases(cwd, run, startIndex, io, sequence, timeoutOptions)
|
|
|
545
604
|
return current;
|
|
546
605
|
}
|
|
547
606
|
const routing = await providerRoutingForPhase(cwd, def.role);
|
|
607
|
+
const executor = await planWorkflowPhaseExecutor({
|
|
608
|
+
taskId: current.taskId,
|
|
609
|
+
runId: current.id,
|
|
610
|
+
phase: def.phase,
|
|
611
|
+
role: def.role,
|
|
612
|
+
mode: timeoutOptions.phaseExecutionMode,
|
|
613
|
+
root: cwd,
|
|
614
|
+
});
|
|
615
|
+
current = await updatePhaseExecutorProvenance(cwd, current, def.phase, executor);
|
|
616
|
+
if (!timeoutOptions.jsonOutput) {
|
|
617
|
+
const label = executor.executor === "runtime-native-subagent"
|
|
618
|
+
? `${executor.runtime} subagent`
|
|
619
|
+
: executor.executor === "queued-runtime-subagent"
|
|
620
|
+
? `${executor.runtime} subagent queued${executor.fallbackReason ? ` (${executor.fallbackReason})` : ""}`
|
|
621
|
+
: `parent-agent fallback${executor.fallbackReason ? ` (${executor.fallbackReason})` : ""}`;
|
|
622
|
+
io.log(` ↳ executor ${label}`);
|
|
623
|
+
}
|
|
624
|
+
if (executor.executor === "queued-runtime-subagent") {
|
|
625
|
+
current = await pauseForQueuedPhaseExecutor(cwd, current, def.phase, {
|
|
626
|
+
reason: executor.fallbackReason ?? "runtime delegation queued",
|
|
627
|
+
...(executor.artifact ? { artifact: executor.artifact } : {}),
|
|
628
|
+
});
|
|
629
|
+
io.log(` ⏳ phase queued — resume when delegation capacity is available: orchestra workflow run --task ${current.taskId} --resume ${current.id}`);
|
|
630
|
+
return current;
|
|
631
|
+
}
|
|
548
632
|
const providerStartedAt = new Date().toISOString();
|
|
549
633
|
const progress = startPhaseProgress({
|
|
550
634
|
io,
|
|
@@ -704,10 +788,11 @@ async function executePhases(cwd, run, startIndex, io, sequence, timeoutOptions)
|
|
|
704
788
|
current = await markRunDone(cwd, current);
|
|
705
789
|
return current;
|
|
706
790
|
}
|
|
707
|
-
async function workflowDryRun(cwd, options, io, taskId, gates, maxIterations, phaseSelection) {
|
|
791
|
+
async function workflowDryRun(cwd, options, io, taskId, gates, maxIterations, phaseSelection, phaseExecutionMode) {
|
|
708
792
|
const phasePlan = await recommendWorkflowPhasePlan(taskId, cwd);
|
|
709
793
|
io.log(`Dry run — no records will be created`);
|
|
710
794
|
io.log(`Task: ${taskId} gates: ${gates} max-iterations: ${maxIterations}`);
|
|
795
|
+
io.log(`Phase execution: ${phaseExecutionMode}`);
|
|
711
796
|
io.log(``);
|
|
712
797
|
for (let i = 0; i < phaseSelection.sequence.length; i++) {
|
|
713
798
|
const def = phaseSelection.sequence[i];
|
|
@@ -730,6 +815,7 @@ async function workflowDryRun(cwd, options, io, taskId, gates, maxIterations, ph
|
|
|
730
815
|
taskId,
|
|
731
816
|
gates,
|
|
732
817
|
maxIterations,
|
|
818
|
+
phaseExecutionMode,
|
|
733
819
|
phases: phaseSelection.sequence,
|
|
734
820
|
skipped: phaseSelection.skipped,
|
|
735
821
|
phasePlan,
|