executant 1.4.2 → 1.4.4
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/index.js
CHANGED
|
@@ -1292,6 +1292,73 @@ async function runPass3Judge(description, workflow2) {
|
|
|
1292
1292
|
return { pass: true, feedback: "", skipped: true };
|
|
1293
1293
|
}
|
|
1294
1294
|
}
|
|
1295
|
+
function isNumericSequence(arr) {
|
|
1296
|
+
return arr.every((item, i) => item === String(i + 1));
|
|
1297
|
+
}
|
|
1298
|
+
function parseSeqCommand(cmd) {
|
|
1299
|
+
const t = cmd.trim();
|
|
1300
|
+
const shorthand = t.match(/^seq\s+(\d+)$/);
|
|
1301
|
+
if (shorthand) return parseInt(shorthand[1], 10);
|
|
1302
|
+
const explicit = t.match(/^seq\s+1\s+(\d+)$/);
|
|
1303
|
+
if (explicit) return parseInt(explicit[1], 10);
|
|
1304
|
+
return null;
|
|
1305
|
+
}
|
|
1306
|
+
function extractCountFromName(name) {
|
|
1307
|
+
const m = name.match(/_of_(\d+)/);
|
|
1308
|
+
return m ? parseInt(m[1], 10) : null;
|
|
1309
|
+
}
|
|
1310
|
+
function normalizeWorkflow(workflow2) {
|
|
1311
|
+
const steps = workflow2.steps.map((step) => {
|
|
1312
|
+
if (Array.isArray(step.forEach) && isNumericSequence(step.forEach)) {
|
|
1313
|
+
const { forEach, ...rest } = step;
|
|
1314
|
+
return { ...rest, repeat: forEach.length };
|
|
1315
|
+
}
|
|
1316
|
+
if (typeof step.forEach === "string") {
|
|
1317
|
+
const n = parseSeqCommand(step.forEach);
|
|
1318
|
+
if (n !== null) {
|
|
1319
|
+
const { forEach, ...rest } = step;
|
|
1320
|
+
return { ...rest, repeat: n };
|
|
1321
|
+
}
|
|
1322
|
+
}
|
|
1323
|
+
const prompt = typeof step.prompt === "string" ? step.prompt : "";
|
|
1324
|
+
if (prompt.includes("{{item}}") && step.forEach === void 0 && step.repeat === void 0) {
|
|
1325
|
+
const n = extractCountFromName(step.name);
|
|
1326
|
+
if (n !== null) return { ...step, repeat: n };
|
|
1327
|
+
}
|
|
1328
|
+
return step;
|
|
1329
|
+
});
|
|
1330
|
+
return { ...workflow2, steps: collapseSequentialSteps(steps) };
|
|
1331
|
+
}
|
|
1332
|
+
function collapseSequentialSteps(steps) {
|
|
1333
|
+
const result = [];
|
|
1334
|
+
let i = 0;
|
|
1335
|
+
while (i < steps.length) {
|
|
1336
|
+
const step = steps[i];
|
|
1337
|
+
if (step.forEach !== void 0 || step.repeat !== void 0) {
|
|
1338
|
+
result.push(step);
|
|
1339
|
+
i++;
|
|
1340
|
+
continue;
|
|
1341
|
+
}
|
|
1342
|
+
const m = step.name.match(/^(.+?)_1$/);
|
|
1343
|
+
if (!m) {
|
|
1344
|
+
result.push(step);
|
|
1345
|
+
i++;
|
|
1346
|
+
continue;
|
|
1347
|
+
}
|
|
1348
|
+
const prefix = m[1];
|
|
1349
|
+
let n = 1;
|
|
1350
|
+
while (i + n < steps.length && steps[i + n].name === `${prefix}_${n + 1}`) n++;
|
|
1351
|
+
if (n < 2) {
|
|
1352
|
+
result.push(step);
|
|
1353
|
+
i++;
|
|
1354
|
+
continue;
|
|
1355
|
+
}
|
|
1356
|
+
const { name, ...rest } = step;
|
|
1357
|
+
result.push({ ...rest, name: `${prefix}_{{item}}`, repeat: n });
|
|
1358
|
+
i += n;
|
|
1359
|
+
}
|
|
1360
|
+
return result;
|
|
1361
|
+
}
|
|
1295
1362
|
async function* streamPlan(args) {
|
|
1296
1363
|
const { description, taskFile } = args;
|
|
1297
1364
|
const skipResearch = args.fast || isSimpleRequest(description);
|
|
@@ -1356,7 +1423,7 @@ async function* streamPlan(args) {
|
|
|
1356
1423
|
${basePrompt}` : basePrompt,
|
|
1357
1424
|
allowedTools: [],
|
|
1358
1425
|
permissionMode: "bypassPermissions",
|
|
1359
|
-
model: "opus",
|
|
1426
|
+
model: skipResearch ? "sonnet" : "opus",
|
|
1360
1427
|
appendSystemPrompt: PLAN_SYSTEM_RULES,
|
|
1361
1428
|
jsonSchema: WORKFLOW_JSON_SCHEMA
|
|
1362
1429
|
};
|
|
@@ -1414,7 +1481,7 @@ ${issues}` };
|
|
|
1414
1481
|
if (!judgeResult.pass) {
|
|
1415
1482
|
yield { type: "plan:warn", message: `Judge rejected plan but retries exhausted: ${judgeResult.feedback}` };
|
|
1416
1483
|
}
|
|
1417
|
-
const { goal, vars, steps, ...rest } = zodResult.data;
|
|
1484
|
+
const { goal, vars, steps, ...rest } = normalizeWorkflow(zodResult.data);
|
|
1418
1485
|
const ordered = { goal, ...vars && { vars }, steps, ...rest };
|
|
1419
1486
|
const yamlContent = dumpYaml(ordered, {
|
|
1420
1487
|
lineWidth: -1,
|
|
@@ -97,6 +97,11 @@ Before finalising your JSON, scan every `prompt` and `command` field you wrote.
|
|
|
97
97
|
For each field, ask: "Does this contain a file path or directory path as a string literal?"
|
|
98
98
|
If yes, extract it to `vars` and replace with `{{var_name}}`.
|
|
99
99
|
|
|
100
|
+
**Pre-Output Self-Review — Repeat (MANDATORY):**
|
|
101
|
+
Scan every `forEach` field you wrote.
|
|
102
|
+
Ask: "Is this array just sequential numbers like `["1","2","3"]` with no meaningful items?"
|
|
103
|
+
If yes, replace the entire `forEach` with `repeat: N` where N is the count. Sequential-number forEach arrays are ALWAYS wrong — they are a misuse of forEach and must be converted to `repeat: N`.
|
|
104
|
+
|
|
100
105
|
## When to Use Each Step Type
|
|
101
106
|
|
|
102
107
|
**Use `prompt` steps (AI-assisted) for:**
|
|
@@ -59,6 +59,15 @@ Are all file paths declared in `vars`?
|
|
|
59
59
|
- Do any `prompt` or `command` fields contain hardcoded file paths or directory paths?
|
|
60
60
|
- Hardcoded paths in steps (not in `vars`) are a violation
|
|
61
61
|
|
|
62
|
+
### 5. Repeat Misuse (if applicable)
|
|
63
|
+
If the user's goal mentions "N times", "repeat N", "N iterations", or "N passes":
|
|
64
|
+
|
|
65
|
+
- Does any step use `forEach` with a sequential numeric array like `["1","2","3","4","5"]`?
|
|
66
|
+
- This is always wrong — `repeat: N` must be used instead of a numeric forEach array
|
|
67
|
+
- Reject and require the offending step be converted to `repeat: N`
|
|
68
|
+
- Does any single step's `prompt` describe doing something "N times" or "across N passes" inline, instead of using `repeat: N`? A step that says "do this 10 times" or "perform N passes" inside its prompt text rather than setting `repeat: N` is wrong — reject it and require it to be restructured as a single-pass prompt with `repeat: N` on the step
|
|
69
|
+
- Are there N consecutive steps with names like `step_1`, `step_2`, `step_3`? Sequential named steps are always wrong when they do the same thing — reject and require a single step with `repeat: N`
|
|
70
|
+
|
|
62
71
|
## Output Format
|
|
63
72
|
|
|
64
73
|
Respond with ONLY a JSON object in this exact shape:
|