workflow-ai 1.0.1 → 1.0.3
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/configs/pipeline.yaml
CHANGED
package/package.json
CHANGED
|
@@ -101,11 +101,44 @@ function readTickets(dir) {
|
|
|
101
101
|
return tickets;
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
+
/**
|
|
105
|
+
* Нормализует входное значение в формат PLAN-NNN.
|
|
106
|
+
* Принимает: "PLAN-007", "7", "007", "plan-7", "plans/PLAN-007.md", "/abs/path/PLAN-007.md"
|
|
107
|
+
*/
|
|
108
|
+
function normalizePlanId(raw) {
|
|
109
|
+
if (!raw) return null;
|
|
110
|
+
|
|
111
|
+
// Извлекаем имя файла если передан путь
|
|
112
|
+
const basename = path.basename(raw, '.md');
|
|
113
|
+
|
|
114
|
+
// Уже в формате PLAN-NNN (регистронезависимо)
|
|
115
|
+
const full = basename.match(/^plan-(\d+)$/i);
|
|
116
|
+
if (full) return `PLAN-${String(parseInt(full[1], 10)).padStart(3, '0')}`;
|
|
117
|
+
|
|
118
|
+
// Просто цифра или число: "7", "007"
|
|
119
|
+
const num = raw.trim().match(/^(\d+)$/);
|
|
120
|
+
if (num) return `PLAN-${String(parseInt(num[1], 10)).padStart(3, '0')}`;
|
|
121
|
+
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Извлекает plan_id из аргументов командной строки (контекст пайплайна)
|
|
127
|
+
*/
|
|
128
|
+
function extractPlanId() {
|
|
129
|
+
const prompt = process.argv.slice(2)[0] || '';
|
|
130
|
+
const match = prompt.match(/plan_id:\s*(\S+)/i);
|
|
131
|
+
return match ? normalizePlanId(match[1]) : null;
|
|
132
|
+
}
|
|
133
|
+
|
|
104
134
|
/**
|
|
105
135
|
* Проверяет все тикеты в backlog/ и возвращает список готовых
|
|
106
136
|
*/
|
|
107
|
-
function checkBacklog() {
|
|
108
|
-
const
|
|
137
|
+
function checkBacklog(planId) {
|
|
138
|
+
const allTickets = readTickets(BACKLOG_DIR);
|
|
139
|
+
const tickets = planId
|
|
140
|
+
? allTickets.filter(t => t.frontmatter.parent_plan === planId)
|
|
141
|
+
: allTickets;
|
|
109
142
|
|
|
110
143
|
const ready = [];
|
|
111
144
|
const waiting = [];
|
|
@@ -134,11 +167,17 @@ function checkBacklog() {
|
|
|
134
167
|
}
|
|
135
168
|
|
|
136
169
|
async function main() {
|
|
170
|
+
const planId = extractPlanId();
|
|
171
|
+
|
|
172
|
+
if (planId) {
|
|
173
|
+
console.log(`[INFO] Filtering by plan_id: ${planId}`);
|
|
174
|
+
}
|
|
175
|
+
|
|
137
176
|
console.log(`[INFO] Scanning backlog/: ${BACKLOG_DIR}`);
|
|
138
177
|
|
|
139
|
-
const { ready, waiting, total } = checkBacklog();
|
|
178
|
+
const { ready, waiting, total } = checkBacklog(planId);
|
|
140
179
|
|
|
141
|
-
console.log(`[INFO] Total in backlog: ${total}`);
|
|
180
|
+
console.log(`[INFO] Total in backlog${planId ? ` (plan ${planId})` : ''}: ${total}`);
|
|
142
181
|
console.log(`[INFO] Ready: ${ready.length}, Waiting: ${waiting.length}`);
|
|
143
182
|
|
|
144
183
|
if (ready.length > 0) {
|
|
@@ -39,6 +39,11 @@ function moveToReview(ticketId) {
|
|
|
39
39
|
const targetPath = path.join(REVIEW_DIR, `${ticketId}.md`);
|
|
40
40
|
|
|
41
41
|
if (!fs.existsSync(sourcePath)) {
|
|
42
|
+
// Ticket may have been moved directly to done/ by the agent — treat as already done
|
|
43
|
+
const donePath = path.join(TICKETS_DIR, 'done', `${ticketId}.md`);
|
|
44
|
+
if (fs.existsSync(donePath)) {
|
|
45
|
+
return { status: 'skipped', ticket_id: ticketId, reason: `${ticketId} already in done/` };
|
|
46
|
+
}
|
|
42
47
|
return { status: 'error', ticket_id: ticketId, error: `${ticketId} not found in in-progress/` };
|
|
43
48
|
}
|
|
44
49
|
|
|
@@ -78,6 +83,10 @@ async function main() {
|
|
|
78
83
|
if (result.status === 'error') {
|
|
79
84
|
process.exit(1);
|
|
80
85
|
}
|
|
86
|
+
|
|
87
|
+
if (result.status === 'skipped') {
|
|
88
|
+
console.log(`[INFO] Skipped: ${result.reason}`);
|
|
89
|
+
}
|
|
81
90
|
}
|
|
82
91
|
|
|
83
92
|
main().catch(e => {
|
|
@@ -5,6 +5,10 @@ description: Проверить результат выполнения зада
|
|
|
5
5
|
|
|
6
6
|
# Проверка результата (Review Result)
|
|
7
7
|
|
|
8
|
+
> **ОБЯЗАТЕЛЬНО:** Последние строки твоего ответа ВСЕГДА должны быть блоком `---RESULT---`.
|
|
9
|
+
> Без этого блока пайплайн не распознает статус и тикет попадёт в `blocked`.
|
|
10
|
+
> Даже если ревью очевидно — всё равно заверши ответ блоком результата.
|
|
11
|
+
|
|
8
12
|
Этот skill проверяет результат выполнения задачи на соответствие критериям готовности (Definition of Done) из тикета.
|
|
9
13
|
|
|
10
14
|
## Когда использовать
|