ultracode-for-codex 0.2.4 → 0.2.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/README.md +9 -2
- package/ULTRACODE_INSTALL.md +8 -2
- package/dist/cli.js +21 -0
- package/dist/runtime/workflow-runtime.d.ts +20 -0
- package/dist/runtime/workflow-runtime.js +95 -2
- package/package.json +1 -1
- package/settings.json +1 -1
- package/skills/ultracode-for-codex/SKILL.md +8 -2
package/README.md
CHANGED
|
@@ -26,7 +26,7 @@ npm run pack:ultracode-for-codex
|
|
|
26
26
|
Install the tarball from a target project:
|
|
27
27
|
|
|
28
28
|
```bash
|
|
29
|
-
npm install --save-dev /path/to/ultracode-for-codex-0.2.
|
|
29
|
+
npm install --save-dev /path/to/ultracode-for-codex-0.2.5.tgz
|
|
30
30
|
```
|
|
31
31
|
|
|
32
32
|
Run a workflow:
|
|
@@ -68,6 +68,10 @@ The built-in `task` and `code-review` workflows use an LLM planner first, then
|
|
|
68
68
|
run work phase by phase. Within each phase, multiple focused Codex subagents run
|
|
69
69
|
in parallel by default, followed by phase and final synthesis. The planner may
|
|
70
70
|
choose a single-agent path only when parallel execution would add risk or waste.
|
|
71
|
+
Planner guidance includes dynamic workflow patterns such as classify-and-act,
|
|
72
|
+
fan-out-and-synthesize, adversarial verification, generate-and-filter,
|
|
73
|
+
tournament, and loop-until-done, so different work types can use different
|
|
74
|
+
phase shapes.
|
|
71
75
|
|
|
72
76
|
## Settings
|
|
73
77
|
|
|
@@ -80,7 +84,7 @@ Package defaults live in `settings.json`:
|
|
|
80
84
|
"progress": "jsonl",
|
|
81
85
|
"permission": "ask",
|
|
82
86
|
"retryLimit": 0,
|
|
83
|
-
"timeoutMs":
|
|
87
|
+
"timeoutMs": 900000,
|
|
84
88
|
"background": {
|
|
85
89
|
"runDir": ".ultracode-for-codex/background/{jobId}",
|
|
86
90
|
"resultFile": "result.json",
|
|
@@ -94,6 +98,7 @@ Package defaults live in `settings.json`:
|
|
|
94
98
|
|
|
95
99
|
Use `--execution attached`, `--progress`, `--permission`, `--retry-limit`, and
|
|
96
100
|
`--timeout-ms` to override settings for one run.
|
|
101
|
+
The package default workflow timeout is `900000` ms, or 15 minutes.
|
|
97
102
|
|
|
98
103
|
## CLI Controls
|
|
99
104
|
|
|
@@ -101,6 +106,8 @@ Use `--execution attached`, `--progress`, `--permission`, `--retry-limit`, and
|
|
|
101
106
|
- The final workflow result is printed as JSON to stdout.
|
|
102
107
|
- JSONL records include `kind`, `version`, `event`, `status`, and `summary`;
|
|
103
108
|
agent records also include stable agent identity and label fields.
|
|
109
|
+
- Built-in `task` and `code-review` emit `workflow.plan.ready` before phase
|
|
110
|
+
agents start, including phase titles and planned agent role labels.
|
|
104
111
|
- Press `Ctrl-C` once to cancel the active workflow.
|
|
105
112
|
- Use `--retry-limit <n>` to retry failed workflows inside the same process.
|
|
106
113
|
- `--timeout-ms` is the workflow timeout and the default per-agent silence
|
package/ULTRACODE_INSTALL.md
CHANGED
|
@@ -31,7 +31,7 @@ npm exec -- ultracode-for-codex --llm-guide
|
|
|
31
31
|
For source-checkout validation, install the generated tarball instead:
|
|
32
32
|
|
|
33
33
|
```bash
|
|
34
|
-
npm install --save-dev ./ultracode-for-codex-0.2.
|
|
34
|
+
npm install --save-dev ./ultracode-for-codex-0.2.5.tgz
|
|
35
35
|
```
|
|
36
36
|
|
|
37
37
|
Optional Codex companion skill:
|
|
@@ -63,6 +63,9 @@ Both start with an LLM planner, execute phase by phase, run multiple focused
|
|
|
63
63
|
Codex subagents in parallel within each phase by default, and synthesize phase
|
|
64
64
|
and final results. The planner chooses a single-agent path only when parallel
|
|
65
65
|
execution would add risk or waste.
|
|
66
|
+
Planner guidance includes classify-and-act, fan-out-and-synthesize,
|
|
67
|
+
adversarial verification, generate-and-filter, tournament, and loop-until-done
|
|
68
|
+
patterns so different work types can use different phase shapes.
|
|
66
69
|
|
|
67
70
|
Settings defaults:
|
|
68
71
|
|
|
@@ -73,7 +76,7 @@ Settings defaults:
|
|
|
73
76
|
"progress": "jsonl",
|
|
74
77
|
"permission": "ask",
|
|
75
78
|
"retryLimit": 0,
|
|
76
|
-
"timeoutMs":
|
|
79
|
+
"timeoutMs": 900000,
|
|
77
80
|
"background": {
|
|
78
81
|
"runDir": ".ultracode-for-codex/background/{jobId}",
|
|
79
82
|
"resultFile": "result.json",
|
|
@@ -89,8 +92,11 @@ Useful controls:
|
|
|
89
92
|
|
|
90
93
|
- Progress events are printed to stderr as JSONL by default.
|
|
91
94
|
- The final workflow result is printed as JSON to stdout.
|
|
95
|
+
- The package default workflow timeout is `900000` ms, or 15 minutes.
|
|
92
96
|
- JSONL records include `kind`, `version`, `event`, `status`, and `summary`;
|
|
93
97
|
agent records also include stable agent identity and label fields.
|
|
98
|
+
- Built-in `task` and `code-review` emit `workflow.plan.ready` before phase
|
|
99
|
+
agents start, including phase titles and planned agent role labels.
|
|
94
100
|
- Press `Ctrl-C` once to cancel the running workflow.
|
|
95
101
|
- Use `--retry-limit <n>` to retry failed runs in the same process.
|
|
96
102
|
- `--timeout-ms` is the workflow timeout and the default per-agent silence
|
package/dist/cli.js
CHANGED
|
@@ -350,6 +350,15 @@ function renderWorkflowEvent(event, progressMode) {
|
|
|
350
350
|
case 'workflow.phase.started':
|
|
351
351
|
process.stderr.write(`[phase] ${event.title}${event.detail ? ` - ${event.detail}` : ''}\n`);
|
|
352
352
|
return;
|
|
353
|
+
case 'workflow.plan.ready':
|
|
354
|
+
process.stderr.write(`[plan] mode=${event.mode} phases=${event.phases.length}${event.rationale ? ` - ${event.rationale}` : ''}\n`);
|
|
355
|
+
for (const [phaseIndex, phase] of event.phases.entries()) {
|
|
356
|
+
process.stderr.write(`[plan] ${phaseIndex + 1}. ${phase.title}${phase.goal ? ` - ${phase.goal}` : ''}\n`);
|
|
357
|
+
for (const agent of phase.agents) {
|
|
358
|
+
process.stderr.write(`[plan] - ${agent.title}${agent.label ? ` (${agent.label})` : ''}${agent.focus ? `: ${agent.focus}` : ''}\n`);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
return;
|
|
353
362
|
case 'workflow.log':
|
|
354
363
|
process.stderr.write(`[log] ${event.message}\n`);
|
|
355
364
|
return;
|
|
@@ -425,6 +434,18 @@ function progressPayloadForEvent(event) {
|
|
|
425
434
|
title: event.title,
|
|
426
435
|
detail: event.detail,
|
|
427
436
|
};
|
|
437
|
+
case 'workflow.plan.ready':
|
|
438
|
+
return {
|
|
439
|
+
event: event.type,
|
|
440
|
+
status: 'planned',
|
|
441
|
+
summary: `Workflow plan ready: ${event.phases.length} phase${event.phases.length === 1 ? '' : 's'}, mode=${event.mode}`,
|
|
442
|
+
taskId: event.taskId,
|
|
443
|
+
runId: event.runId,
|
|
444
|
+
mode: event.mode,
|
|
445
|
+
rationale: event.rationale,
|
|
446
|
+
phaseCount: event.phases.length,
|
|
447
|
+
planPhases: event.phases,
|
|
448
|
+
};
|
|
428
449
|
case 'workflow.log':
|
|
429
450
|
return {
|
|
430
451
|
event: event.type,
|
|
@@ -4,6 +4,18 @@ export type WorkflowTaskStatus = 'running' | 'completed' | 'failed';
|
|
|
4
4
|
export type WorkflowTaskType = 'local_workflow';
|
|
5
5
|
export type WorkflowSource = 'inline' | 'script_path' | 'project' | 'user' | 'plugin' | 'built_in';
|
|
6
6
|
export type WorkflowPermissionDecision = 'allow' | 'deny';
|
|
7
|
+
export interface WorkflowPlanAgent {
|
|
8
|
+
readonly id?: string;
|
|
9
|
+
readonly title: string;
|
|
10
|
+
readonly focus?: string;
|
|
11
|
+
readonly label?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface WorkflowPlanPhase {
|
|
14
|
+
readonly id?: string;
|
|
15
|
+
readonly title: string;
|
|
16
|
+
readonly goal?: string;
|
|
17
|
+
readonly agents: readonly WorkflowPlanAgent[];
|
|
18
|
+
}
|
|
7
19
|
export type WorkflowEvent = {
|
|
8
20
|
readonly type: 'workflow.started';
|
|
9
21
|
readonly taskId: string;
|
|
@@ -20,6 +32,13 @@ export type WorkflowEvent = {
|
|
|
20
32
|
readonly phaseIndex: number;
|
|
21
33
|
readonly title: string;
|
|
22
34
|
readonly detail?: string;
|
|
35
|
+
} | {
|
|
36
|
+
readonly type: 'workflow.plan.ready';
|
|
37
|
+
readonly taskId: string;
|
|
38
|
+
readonly runId: string;
|
|
39
|
+
readonly mode: string;
|
|
40
|
+
readonly rationale?: string;
|
|
41
|
+
readonly phases: readonly WorkflowPlanPhase[];
|
|
23
42
|
} | {
|
|
24
43
|
readonly type: 'workflow.log';
|
|
25
44
|
readonly taskId: string;
|
|
@@ -250,6 +269,7 @@ export declare class WorkflowTaskRegistry implements WorkflowRuntime {
|
|
|
250
269
|
private runAgentAttempt;
|
|
251
270
|
private parallel;
|
|
252
271
|
private pipeline;
|
|
272
|
+
private announcePlan;
|
|
253
273
|
private phase;
|
|
254
274
|
private completeTask;
|
|
255
275
|
private failTask;
|
|
@@ -98,6 +98,16 @@ const WORKSPACE_CONTEXT_PRIORITY_FILES = new Set([
|
|
|
98
98
|
'package.json',
|
|
99
99
|
'tsconfig.json',
|
|
100
100
|
]);
|
|
101
|
+
const DYNAMIC_WORKFLOW_PATTERN_GUIDANCE = [
|
|
102
|
+
'Use dynamic workflow patterns intentionally:',
|
|
103
|
+
'- classify-and-act: classify the request, risk, or repository area before choosing phase shape.',
|
|
104
|
+
'- fan-out-and-synthesize: split independent lenses across parallel agents, then merge evidence.',
|
|
105
|
+
'- adversarial verification: assign at least one agent to challenge correctness, security, or assumptions on high-risk work.',
|
|
106
|
+
'- generate-and-filter: create candidate approaches or fixes, then select by evidence and constraints.',
|
|
107
|
+
'- tournament: compare competing alternatives when the best path is unclear.',
|
|
108
|
+
'- loop-until-done: iterate repair and verification only when there is a clear stop condition.',
|
|
109
|
+
'Prefer pipelines when later phases need earlier summaries; prefer parallel agents when independent evidence can be gathered at the same time.',
|
|
110
|
+
].join('\n');
|
|
101
111
|
const DEFAULT_BUILTIN_WORKFLOWS = [
|
|
102
112
|
{
|
|
103
113
|
name: 'task',
|
|
@@ -106,7 +116,7 @@ const DEFAULT_BUILTIN_WORKFLOWS = [
|
|
|
106
116
|
description: 'Run an LLM-planned phase-wise parallel task workflow',
|
|
107
117
|
defaultPrompt: 'Complete the requested repository task.',
|
|
108
118
|
plannerKind: 'general task',
|
|
109
|
-
plannerGuidance: 'Plan phases that make the work faster and more accurate through parallel agents. Default to phase_parallel. Choose single only for tiny changes, strictly sequential investigations, or one indivisible failure mode.',
|
|
119
|
+
plannerGuidance: 'Plan phases that make the work faster and more accurate through parallel agents. Default to phase_parallel. Choose single only for tiny changes, strictly sequential investigations, or one indivisible failure mode. Pick workflow patterns that match the request instead of using one fixed shape.',
|
|
110
120
|
agentGuidance: 'Complete the assigned phase work. Prefer concrete evidence, file paths, commands, and risks over broad narration.',
|
|
111
121
|
finalGuidance: 'Return the completed task result, key evidence, decisions made, verification status, and residual risk.',
|
|
112
122
|
}),
|
|
@@ -118,7 +128,7 @@ const DEFAULT_BUILTIN_WORKFLOWS = [
|
|
|
118
128
|
description: 'Run an LLM-planned phase-wise parallel code review workflow',
|
|
119
129
|
defaultPrompt: 'Review the current repository for correctness risks.',
|
|
120
130
|
plannerKind: 'code review',
|
|
121
|
-
plannerGuidance: 'Plan an effective code review. Default to phase_parallel with multiple focused reviewers per phase. Commonly useful lenses include runtime correctness, security/capability boundaries, API/CLI contracts, persistence/retry/cancel behavior, and test coverage.
|
|
131
|
+
plannerGuidance: 'Plan an effective code review. Default to phase_parallel with multiple focused reviewers per phase. Commonly useful lenses include runtime correctness, security/capability boundaries, API/CLI contracts, persistence/retry/cancel behavior, and test coverage. Prefer fan-out-and-synthesize plus adversarial verification unless the diff is tiny or one indivisible failure mode.',
|
|
122
132
|
agentGuidance: 'Return material findings only. Prioritize root cause, severity, exact file/line evidence, reproduction or impact, and residual risk.',
|
|
123
133
|
finalGuidance: 'Return findings ordered by severity with exact file/line references. Deduplicate overlaps, preserve dissent or uncertainty, and say clearly if there are no material findings.',
|
|
124
134
|
}),
|
|
@@ -152,6 +162,8 @@ const plan = await agent([
|
|
|
152
162
|
${JSON.stringify(`Plan the phase-wise execution strategy for ${input.plannerKind}.`)},
|
|
153
163
|
"",
|
|
154
164
|
${JSON.stringify(input.plannerGuidance)},
|
|
165
|
+
"",
|
|
166
|
+
${JSON.stringify(DYNAMIC_WORKFLOW_PATTERN_GUIDANCE)},
|
|
155
167
|
"A phase runs after previous phase summaries are available. Within each phase, use parallel agents by default.",
|
|
156
168
|
"Return 1 to 4 phases. For ordinary work, prefer 2 phases with 2 to 4 parallel agents each. Use concise stable ids.",
|
|
157
169
|
"",
|
|
@@ -202,6 +214,23 @@ const plan = await agent([
|
|
|
202
214
|
}
|
|
203
215
|
});
|
|
204
216
|
const selectedPhases = plan.mode === "single" ? [plan.phases[0]] : plan.phases;
|
|
217
|
+
announcePlan({
|
|
218
|
+
mode: plan.mode,
|
|
219
|
+
rationale: plan.rationale,
|
|
220
|
+
phases: selectedPhases.map((phasePlan) => ({
|
|
221
|
+
id: phasePlan.id,
|
|
222
|
+
title: phasePlan.title,
|
|
223
|
+
goal: phasePlan.goal,
|
|
224
|
+
agents: (plan.mode === "single" ? [phasePlan.agents[0]] : phasePlan.agents).map((phaseAgent) => ({
|
|
225
|
+
id: phaseAgent.id,
|
|
226
|
+
title: phaseAgent.title,
|
|
227
|
+
focus: phaseAgent.focus,
|
|
228
|
+
label: plan.mode === "single"
|
|
229
|
+
? ${JSON.stringify(`${input.name}-single`)}
|
|
230
|
+
: ${JSON.stringify(`${input.name}-`)} + phasePlan.id + "-" + phaseAgent.id
|
|
231
|
+
}))
|
|
232
|
+
}))
|
|
233
|
+
});
|
|
205
234
|
if (plan.mode === "single") {
|
|
206
235
|
const singlePhase = selectedPhases[0];
|
|
207
236
|
const singleAgent = singlePhase.agents[0];
|
|
@@ -1048,6 +1077,7 @@ export class WorkflowTaskRegistry {
|
|
|
1048
1077
|
host.workspaceContext = hardenCallable((options) => {
|
|
1049
1078
|
return this.trackWorkflowPromise(ctx, this.workspaceContext(ctx, options));
|
|
1050
1079
|
});
|
|
1080
|
+
host.announcePlan = hardenCallable((plan) => this.announcePlan(ctx, plan));
|
|
1051
1081
|
host.phase = hardenCallable((title) => this.phase(ctx, title));
|
|
1052
1082
|
host.log = hardenCallable(log);
|
|
1053
1083
|
host.consoleLog = hardenCallable((...values) => {
|
|
@@ -1494,6 +1524,18 @@ export class WorkflowTaskRegistry {
|
|
|
1494
1524
|
return current;
|
|
1495
1525
|
});
|
|
1496
1526
|
}
|
|
1527
|
+
announcePlan(ctx, plan) {
|
|
1528
|
+
if (ctx.controller.signal.aborted || ctx.task.status !== 'running') {
|
|
1529
|
+
throw workflowInputError('Workflow is aborted.');
|
|
1530
|
+
}
|
|
1531
|
+
const normalized = normalizeWorkflowExecutionPlan(plan);
|
|
1532
|
+
this.emit(ctx.task, {
|
|
1533
|
+
type: 'workflow.plan.ready',
|
|
1534
|
+
taskId: ctx.task.taskId,
|
|
1535
|
+
runId: ctx.task.runId,
|
|
1536
|
+
...normalized,
|
|
1537
|
+
});
|
|
1538
|
+
}
|
|
1497
1539
|
phase(ctx, title) {
|
|
1498
1540
|
if (typeof title !== 'string' || title.trim() === '') {
|
|
1499
1541
|
throw workflowInputError('phase() requires a non-empty string title.');
|
|
@@ -2929,6 +2971,7 @@ function installWorkflowVmGlobals(context, globals) {
|
|
|
2929
2971
|
' define(globalThis, "parallel", { value: (...values) => __host.parallel(...values), writable: false, configurable: false });',
|
|
2930
2972
|
' define(globalThis, "pipeline", { value: (...values) => __host.pipeline(...values), writable: false, configurable: false });',
|
|
2931
2973
|
' define(globalThis, "workspaceContext", { value: (...values) => __host.workspaceContext(...values), writable: false, configurable: false });',
|
|
2974
|
+
' define(globalThis, "announcePlan", { value: (...values) => __host.announcePlan(...values), writable: false, configurable: false });',
|
|
2932
2975
|
' define(globalThis, "phase", { value: (...values) => __host.phase(...values), writable: false, configurable: false });',
|
|
2933
2976
|
' define(globalThis, "log", { value: (...values) => __host.log(...values), writable: false, configurable: false });',
|
|
2934
2977
|
' define(globalThis, "workflow", { value: (...values) => __host.workflow(...values), writable: false, configurable: false });',
|
|
@@ -3612,6 +3655,56 @@ function previewValue(value, limit) {
|
|
|
3612
3655
|
: JSON.stringify(value) ?? String(value);
|
|
3613
3656
|
return preview(text, limit);
|
|
3614
3657
|
}
|
|
3658
|
+
function normalizeWorkflowExecutionPlan(value) {
|
|
3659
|
+
const record = asRecord(value);
|
|
3660
|
+
if (!record)
|
|
3661
|
+
throw workflowInputError('announcePlan(plan) requires a plan object.');
|
|
3662
|
+
const mode = boundedPlanString(record.mode, 'phase_parallel', 48);
|
|
3663
|
+
const rationale = optionalBoundedPlanString(record.rationale, 400);
|
|
3664
|
+
const rawPhases = Array.isArray(record.phases) ? Array.from(record.phases) : [];
|
|
3665
|
+
if (rawPhases.length === 0)
|
|
3666
|
+
throw workflowInputError('announcePlan(plan) requires at least one phase.');
|
|
3667
|
+
const phases = rawPhases.slice(0, 16).map((phaseValue, phaseIndex) => {
|
|
3668
|
+
const phase = asRecord(phaseValue);
|
|
3669
|
+
if (!phase)
|
|
3670
|
+
throw workflowInputError(`announcePlan(plan).phases[${phaseIndex}] must be an object.`);
|
|
3671
|
+
const rawAgents = Array.isArray(phase.agents) ? Array.from(phase.agents) : [];
|
|
3672
|
+
if (rawAgents.length === 0) {
|
|
3673
|
+
throw workflowInputError(`announcePlan(plan).phases[${phaseIndex}].agents requires at least one agent.`);
|
|
3674
|
+
}
|
|
3675
|
+
return {
|
|
3676
|
+
...(typeof phase.id === 'string' && phase.id.trim() ? { id: boundedPlanString(phase.id, '', 48) } : {}),
|
|
3677
|
+
title: boundedPlanString(phase.title, `Phase ${phaseIndex + 1}`, 96),
|
|
3678
|
+
...(typeof phase.goal === 'string' && phase.goal.trim() ? { goal: boundedPlanString(phase.goal, '', 600) } : {}),
|
|
3679
|
+
agents: rawAgents.slice(0, 16).map((agentValue, agentIndex) => {
|
|
3680
|
+
const agent = asRecord(agentValue);
|
|
3681
|
+
if (!agent) {
|
|
3682
|
+
throw workflowInputError(`announcePlan(plan).phases[${phaseIndex}].agents[${agentIndex}] must be an object.`);
|
|
3683
|
+
}
|
|
3684
|
+
return {
|
|
3685
|
+
...(typeof agent.id === 'string' && agent.id.trim() ? { id: boundedPlanString(agent.id, '', 48) } : {}),
|
|
3686
|
+
title: boundedPlanString(agent.title, `Agent ${agentIndex + 1}`, 96),
|
|
3687
|
+
...(typeof agent.focus === 'string' && agent.focus.trim() ? { focus: boundedPlanString(agent.focus, '', 600) } : {}),
|
|
3688
|
+
...(typeof agent.label === 'string' && agent.label.trim() ? { label: boundedPlanString(agent.label, '', 96) } : {}),
|
|
3689
|
+
};
|
|
3690
|
+
}),
|
|
3691
|
+
};
|
|
3692
|
+
});
|
|
3693
|
+
return {
|
|
3694
|
+
mode,
|
|
3695
|
+
...(rationale ? { rationale } : {}),
|
|
3696
|
+
phases,
|
|
3697
|
+
};
|
|
3698
|
+
}
|
|
3699
|
+
function boundedPlanString(value, fallback, limit) {
|
|
3700
|
+
const text = typeof value === 'string' && value.trim() ? value.trim() : fallback;
|
|
3701
|
+
return preview(text, limit);
|
|
3702
|
+
}
|
|
3703
|
+
function optionalBoundedPlanString(value, limit) {
|
|
3704
|
+
if (typeof value !== 'string' || !value.trim())
|
|
3705
|
+
return undefined;
|
|
3706
|
+
return boundedPlanString(value, '', limit);
|
|
3707
|
+
}
|
|
3615
3708
|
function asRecord(value) {
|
|
3616
3709
|
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
3617
3710
|
return null;
|
package/package.json
CHANGED
package/settings.json
CHANGED
|
@@ -22,6 +22,9 @@ The default Ultracode work shape is phase-wise parallel execution: built-in
|
|
|
22
22
|
phase with parallel focused subagents by default, followed by phase and final
|
|
23
23
|
synthesis. A single-agent path is reserved for cases where the planner judges
|
|
24
24
|
parallel execution risky or wasteful.
|
|
25
|
+
Planner guidance includes classify-and-act, fan-out-and-synthesize,
|
|
26
|
+
adversarial verification, generate-and-filter, tournament, and loop-until-done
|
|
27
|
+
patterns so workflow shape can follow the task instead of a fixed template.
|
|
25
28
|
|
|
26
29
|
## Install And Run
|
|
27
30
|
|
|
@@ -41,7 +44,7 @@ For source-checkout validation before publish:
|
|
|
41
44
|
|
|
42
45
|
```bash
|
|
43
46
|
npm run pack:ultracode-for-codex
|
|
44
|
-
npm install --save-dev ./artifacts/ultracode-for-codex-0.2.
|
|
47
|
+
npm install --save-dev ./artifacts/ultracode-for-codex-0.2.5.tgz
|
|
45
48
|
```
|
|
46
49
|
|
|
47
50
|
CLI behavior:
|
|
@@ -53,10 +56,13 @@ CLI behavior:
|
|
|
53
56
|
- attached final workflow result prints as JSON to stdout;
|
|
54
57
|
- JSONL records include `kind`, `version`, `event`, `status`, and `summary`,
|
|
55
58
|
with agent identity and label fields on agent records;
|
|
59
|
+
- built-in `task` and `code-review` emit `workflow.plan.ready` before phase
|
|
60
|
+
agents start, including phase titles and planned agent role labels;
|
|
56
61
|
- `Ctrl-C` cancels the active attached workflow;
|
|
57
62
|
- `--retry-limit <n>` retries failed workflows inside the same process;
|
|
58
63
|
- `--timeout-ms` is the workflow timeout and the default per-agent silence
|
|
59
|
-
budget;
|
|
64
|
+
budget; the package default is `900000` ms, or 15 minutes, and it is not
|
|
65
|
+
divided by the retry budget.
|
|
60
66
|
- `--permission ask|allow|deny` handles project/user/plugin/scriptPath reviews.
|
|
61
67
|
- `--progress plain` switches to human-readable progress lines.
|
|
62
68
|
- background file locations are controlled by `workflow.background` in
|