agentweaver 0.1.2 → 0.1.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.
Files changed (61) hide show
  1. package/README.md +58 -23
  2. package/dist/artifacts.js +58 -2
  3. package/dist/executors/claude-executor.js +12 -2
  4. package/dist/executors/claude-summary-executor.js +1 -1
  5. package/dist/executors/codex-docker-executor.js +1 -1
  6. package/dist/executors/codex-local-executor.js +1 -1
  7. package/dist/executors/configs/claude-config.js +2 -1
  8. package/dist/executors/verify-build-executor.js +110 -9
  9. package/dist/index.js +466 -452
  10. package/dist/interactive-ui.js +538 -194
  11. package/dist/jira.js +3 -1
  12. package/dist/pipeline/auto-flow.js +9 -0
  13. package/dist/pipeline/checks.js +5 -0
  14. package/dist/pipeline/context.js +2 -0
  15. package/dist/pipeline/declarative-flow-runner.js +262 -0
  16. package/dist/pipeline/declarative-flows.js +24 -0
  17. package/dist/pipeline/flow-specs/auto.json +485 -0
  18. package/dist/pipeline/flow-specs/bug-analyze.json +140 -0
  19. package/dist/pipeline/flow-specs/bug-fix.json +44 -0
  20. package/dist/pipeline/flow-specs/implement.json +47 -0
  21. package/dist/pipeline/flow-specs/mr-description.json +61 -0
  22. package/dist/pipeline/flow-specs/plan.json +88 -0
  23. package/dist/pipeline/flow-specs/preflight.json +174 -0
  24. package/dist/pipeline/flow-specs/review-fix.json +76 -0
  25. package/dist/pipeline/flow-specs/review.json +233 -0
  26. package/dist/pipeline/flow-specs/run-linter-loop.json +149 -0
  27. package/dist/pipeline/flow-specs/run-tests-loop.json +149 -0
  28. package/dist/pipeline/flow-specs/task-describe.json +61 -0
  29. package/dist/pipeline/flow-specs/test-fix.json +24 -0
  30. package/dist/pipeline/flow-specs/test-linter-fix.json +24 -0
  31. package/dist/pipeline/flow-specs/test.json +19 -0
  32. package/dist/pipeline/flows/implement-flow.js +3 -4
  33. package/dist/pipeline/flows/preflight-flow.js +17 -57
  34. package/dist/pipeline/flows/review-fix-flow.js +3 -4
  35. package/dist/pipeline/flows/review-flow.js +8 -4
  36. package/dist/pipeline/flows/test-fix-flow.js +3 -4
  37. package/dist/pipeline/node-registry.js +74 -0
  38. package/dist/pipeline/node-runner.js +9 -3
  39. package/dist/pipeline/nodes/build-failure-summary-node.js +4 -4
  40. package/dist/pipeline/nodes/claude-prompt-node.js +54 -0
  41. package/dist/pipeline/nodes/claude-summary-node.js +12 -6
  42. package/dist/pipeline/nodes/codex-docker-prompt-node.js +1 -0
  43. package/dist/pipeline/nodes/codex-local-prompt-node.js +32 -0
  44. package/dist/pipeline/nodes/file-check-node.js +15 -0
  45. package/dist/pipeline/nodes/flow-run-node.js +40 -0
  46. package/dist/pipeline/nodes/summary-file-load-node.js +16 -0
  47. package/dist/pipeline/nodes/task-summary-node.js +12 -6
  48. package/dist/pipeline/nodes/verify-build-node.js +1 -0
  49. package/dist/pipeline/prompt-registry.js +27 -0
  50. package/dist/pipeline/prompt-runtime.js +18 -0
  51. package/dist/pipeline/registry.js +0 -2
  52. package/dist/pipeline/spec-compiler.js +213 -0
  53. package/dist/pipeline/spec-loader.js +14 -0
  54. package/dist/pipeline/spec-types.js +1 -0
  55. package/dist/pipeline/spec-validator.js +302 -0
  56. package/dist/pipeline/value-resolver.js +217 -0
  57. package/dist/prompts.js +22 -3
  58. package/dist/runtime/process-runner.js +24 -23
  59. package/dist/structured-artifacts.js +178 -0
  60. package/dist/tui.js +39 -0
  61. package/package.json +2 -2
@@ -0,0 +1,149 @@
1
+ {
2
+ "kind": "run-linter-loop-flow",
3
+ "version": 1,
4
+ "phases": [
5
+ {
6
+ "id": "run_linter_try_1",
7
+ "steps": [
8
+ {
9
+ "id": "run_linter",
10
+ "node": "verify-build",
11
+ "params": {
12
+ "dockerComposeFile": { "ref": "params.dockerComposeFile" },
13
+ "labelText": {
14
+ "const": "Running run_linter.sh in isolated Docker (attempt 1)"
15
+ },
16
+ "service": { "const": "run-linter" }
17
+ },
18
+ "stopFlowIf": {
19
+ "equals": [
20
+ { "ref": "steps.run_linter_try_1.run_linter.outputs.parsed.ok" },
21
+ { "const": true }
22
+ ]
23
+ }
24
+ },
25
+ {
26
+ "id": "fix_linter",
27
+ "when": {
28
+ "equals": [
29
+ { "ref": "steps.run_linter_try_1.run_linter.outputs.parsed.ok" },
30
+ { "const": false }
31
+ ]
32
+ },
33
+ "node": "codex-local-prompt",
34
+ "prompt": {
35
+ "templateRef": "run-linter-loop-fix",
36
+ "extraPrompt": {
37
+ "appendPrompt": {
38
+ "base": { "ref": "params.extraPrompt" },
39
+ "suffix": {
40
+ "template": "Последний результат run_linter.sh: exitCode={exit_code}, summary={summary}. Исправь только то, что мешает успешному прохождению проверки.",
41
+ "vars": {
42
+ "exit_code": { "ref": "steps.run_linter_try_1.run_linter.outputs.parsed.exitCode" },
43
+ "summary": { "ref": "steps.run_linter_try_1.run_linter.outputs.parsed.summary" }
44
+ }
45
+ }
46
+ }
47
+ },
48
+ "format": "task-prompt"
49
+ },
50
+ "params": {
51
+ "labelText": {
52
+ "const": "Running Codex linter loop fix (attempt 1)"
53
+ },
54
+ "model": { "const": "gpt-5.4" }
55
+ }
56
+ }
57
+ ]
58
+ },
59
+ {
60
+ "repeat": {
61
+ "var": "attempt",
62
+ "from": 2,
63
+ "to": 5
64
+ },
65
+ "phases": [
66
+ {
67
+ "id": "run_linter_try_${attempt}",
68
+ "when": {
69
+ "equals": [
70
+ { "ref": "steps.run_linter_try_${attempt_minus_one}.run_linter.outputs.parsed.ok" },
71
+ { "const": false }
72
+ ]
73
+ },
74
+ "steps": [
75
+ {
76
+ "id": "run_linter",
77
+ "node": "verify-build",
78
+ "params": {
79
+ "dockerComposeFile": { "ref": "params.dockerComposeFile" },
80
+ "labelText": {
81
+ "template": "Running run_linter.sh in isolated Docker (attempt ${attempt})"
82
+ },
83
+ "service": { "const": "run-linter" }
84
+ },
85
+ "stopFlowIf": {
86
+ "equals": [
87
+ { "ref": "steps.run_linter_try_${attempt}.run_linter.outputs.parsed.ok" },
88
+ { "const": true }
89
+ ]
90
+ }
91
+ },
92
+ {
93
+ "id": "fix_linter",
94
+ "when": {
95
+ "equals": [
96
+ { "ref": "steps.run_linter_try_${attempt}.run_linter.outputs.parsed.ok" },
97
+ { "const": false }
98
+ ]
99
+ },
100
+ "node": "codex-local-prompt",
101
+ "prompt": {
102
+ "templateRef": "run-linter-loop-fix",
103
+ "extraPrompt": {
104
+ "appendPrompt": {
105
+ "base": { "ref": "params.extraPrompt" },
106
+ "suffix": {
107
+ "template": "Последний результат run_linter.sh: exitCode={exit_code}, summary={summary}. Исправь только то, что мешает успешному прохождению проверки.",
108
+ "vars": {
109
+ "exit_code": { "ref": "steps.run_linter_try_${attempt}.run_linter.outputs.parsed.exitCode" },
110
+ "summary": { "ref": "steps.run_linter_try_${attempt}.run_linter.outputs.parsed.summary" }
111
+ }
112
+ }
113
+ }
114
+ },
115
+ "format": "task-prompt"
116
+ },
117
+ "params": {
118
+ "labelText": {
119
+ "template": "Running Codex linter loop fix (attempt ${attempt})"
120
+ },
121
+ "model": { "const": "gpt-5.4" }
122
+ }
123
+ }
124
+ ]
125
+ }
126
+ ]
127
+ },
128
+ {
129
+ "id": "run_linter_failed",
130
+ "steps": [
131
+ {
132
+ "id": "assert_run_linter_success",
133
+ "node": "file-check",
134
+ "params": {
135
+ "path": { "ref": "params.dockerComposeFile" }
136
+ },
137
+ "expect": [
138
+ {
139
+ "kind": "step-output",
140
+ "value": { "ref": "steps.run_linter_try_5.run_linter.outputs.parsed.ok" },
141
+ "equals": { "const": true },
142
+ "message": "run-linter-loop exhausted all attempts without a successful run_linter.sh execution."
143
+ }
144
+ ]
145
+ }
146
+ ]
147
+ }
148
+ ]
149
+ }
@@ -0,0 +1,149 @@
1
+ {
2
+ "kind": "run-tests-loop-flow",
3
+ "version": 1,
4
+ "phases": [
5
+ {
6
+ "id": "run_tests_try_1",
7
+ "steps": [
8
+ {
9
+ "id": "run_tests",
10
+ "node": "verify-build",
11
+ "params": {
12
+ "dockerComposeFile": { "ref": "params.dockerComposeFile" },
13
+ "labelText": {
14
+ "const": "Running run_tests.sh in isolated Docker (attempt 1)"
15
+ },
16
+ "service": { "const": "run-tests" }
17
+ },
18
+ "stopFlowIf": {
19
+ "equals": [
20
+ { "ref": "steps.run_tests_try_1.run_tests.outputs.parsed.ok" },
21
+ { "const": true }
22
+ ]
23
+ }
24
+ },
25
+ {
26
+ "id": "fix_tests",
27
+ "when": {
28
+ "equals": [
29
+ { "ref": "steps.run_tests_try_1.run_tests.outputs.parsed.ok" },
30
+ { "const": false }
31
+ ]
32
+ },
33
+ "node": "codex-local-prompt",
34
+ "prompt": {
35
+ "templateRef": "run-tests-loop-fix",
36
+ "extraPrompt": {
37
+ "appendPrompt": {
38
+ "base": { "ref": "params.extraPrompt" },
39
+ "suffix": {
40
+ "template": "Последний результат run_tests.sh: exitCode={exit_code}, summary={summary}. Исправь только то, что мешает успешному прохождению проверки.",
41
+ "vars": {
42
+ "exit_code": { "ref": "steps.run_tests_try_1.run_tests.outputs.parsed.exitCode" },
43
+ "summary": { "ref": "steps.run_tests_try_1.run_tests.outputs.parsed.summary" }
44
+ }
45
+ }
46
+ }
47
+ },
48
+ "format": "task-prompt"
49
+ },
50
+ "params": {
51
+ "labelText": {
52
+ "const": "Running Codex tests loop fix (attempt 1)"
53
+ },
54
+ "model": { "const": "gpt-5.4" }
55
+ }
56
+ }
57
+ ]
58
+ },
59
+ {
60
+ "repeat": {
61
+ "var": "attempt",
62
+ "from": 2,
63
+ "to": 5
64
+ },
65
+ "phases": [
66
+ {
67
+ "id": "run_tests_try_${attempt}",
68
+ "when": {
69
+ "equals": [
70
+ { "ref": "steps.run_tests_try_${attempt_minus_one}.run_tests.outputs.parsed.ok" },
71
+ { "const": false }
72
+ ]
73
+ },
74
+ "steps": [
75
+ {
76
+ "id": "run_tests",
77
+ "node": "verify-build",
78
+ "params": {
79
+ "dockerComposeFile": { "ref": "params.dockerComposeFile" },
80
+ "labelText": {
81
+ "template": "Running run_tests.sh in isolated Docker (attempt ${attempt})"
82
+ },
83
+ "service": { "const": "run-tests" }
84
+ },
85
+ "stopFlowIf": {
86
+ "equals": [
87
+ { "ref": "steps.run_tests_try_${attempt}.run_tests.outputs.parsed.ok" },
88
+ { "const": true }
89
+ ]
90
+ }
91
+ },
92
+ {
93
+ "id": "fix_tests",
94
+ "when": {
95
+ "equals": [
96
+ { "ref": "steps.run_tests_try_${attempt}.run_tests.outputs.parsed.ok" },
97
+ { "const": false }
98
+ ]
99
+ },
100
+ "node": "codex-local-prompt",
101
+ "prompt": {
102
+ "templateRef": "run-tests-loop-fix",
103
+ "extraPrompt": {
104
+ "appendPrompt": {
105
+ "base": { "ref": "params.extraPrompt" },
106
+ "suffix": {
107
+ "template": "Последний результат run_tests.sh: exitCode={exit_code}, summary={summary}. Исправь только то, что мешает успешному прохождению проверки.",
108
+ "vars": {
109
+ "exit_code": { "ref": "steps.run_tests_try_${attempt}.run_tests.outputs.parsed.exitCode" },
110
+ "summary": { "ref": "steps.run_tests_try_${attempt}.run_tests.outputs.parsed.summary" }
111
+ }
112
+ }
113
+ }
114
+ },
115
+ "format": "task-prompt"
116
+ },
117
+ "params": {
118
+ "labelText": {
119
+ "template": "Running Codex tests loop fix (attempt ${attempt})"
120
+ },
121
+ "model": { "const": "gpt-5.4" }
122
+ }
123
+ }
124
+ ]
125
+ }
126
+ ]
127
+ },
128
+ {
129
+ "id": "run_tests_failed",
130
+ "steps": [
131
+ {
132
+ "id": "assert_run_tests_success",
133
+ "node": "file-check",
134
+ "params": {
135
+ "path": { "ref": "params.dockerComposeFile" }
136
+ },
137
+ "expect": [
138
+ {
139
+ "kind": "step-output",
140
+ "value": { "ref": "steps.run_tests_try_5.run_tests.outputs.parsed.ok" },
141
+ "equals": { "const": true },
142
+ "message": "run-tests-loop exhausted all attempts without a successful run_tests.sh execution."
143
+ }
144
+ ]
145
+ }
146
+ ]
147
+ }
148
+ ]
149
+ }
@@ -0,0 +1,61 @@
1
+ {
2
+ "kind": "task-describe-flow",
3
+ "version": 1,
4
+ "phases": [
5
+ {
6
+ "id": "task_describe",
7
+ "steps": [
8
+ {
9
+ "id": "run_codex_task_describe",
10
+ "node": "codex-local-prompt",
11
+ "prompt": {
12
+ "inlineTemplate": "Посмотри задачу в {jira_task_file}. Проанализируй код и оформи описание для Jira, без лишних подробностей. Запиши в {jira_description_file}.",
13
+ "vars": {
14
+ "jira_task_file": {
15
+ "artifact": {
16
+ "kind": "jira-task-file",
17
+ "taskKey": { "ref": "params.taskKey" }
18
+ }
19
+ },
20
+ "jira_description_file": {
21
+ "artifact": {
22
+ "kind": "jira-description-file",
23
+ "taskKey": { "ref": "params.taskKey" }
24
+ }
25
+ }
26
+ },
27
+ "extraPrompt": { "ref": "params.extraPrompt" },
28
+ "format": "task-prompt"
29
+ },
30
+ "params": {
31
+ "labelText": { "const": "Running Codex task description mode" },
32
+ "model": { "const": "gpt-5.4" },
33
+ "requiredArtifacts": {
34
+ "list": [
35
+ {
36
+ "artifact": {
37
+ "kind": "jira-description-file",
38
+ "taskKey": { "ref": "params.taskKey" }
39
+ }
40
+ }
41
+ ]
42
+ }
43
+ },
44
+ "expect": [
45
+ {
46
+ "kind": "require-file",
47
+ "when": { "not": { "ref": "context.dryRun" } },
48
+ "path": {
49
+ "artifact": {
50
+ "kind": "jira-description-file",
51
+ "taskKey": { "ref": "params.taskKey" }
52
+ }
53
+ },
54
+ "message": "Task describe mode did not produce the Jira description artifact."
55
+ }
56
+ ]
57
+ }
58
+ ]
59
+ }
60
+ ]
61
+ }
@@ -0,0 +1,24 @@
1
+ {
2
+ "kind": "test-fix-flow",
3
+ "version": 1,
4
+ "phases": [
5
+ {
6
+ "id": "test-fix",
7
+ "steps": [
8
+ {
9
+ "id": "run_codex_test_fix",
10
+ "node": "codex-local-prompt",
11
+ "prompt": {
12
+ "templateRef": "test-fix",
13
+ "extraPrompt": { "ref": "params.extraPrompt" },
14
+ "format": "task-prompt"
15
+ },
16
+ "params": {
17
+ "labelText": { "const": "Running Codex test-fix mode locally" },
18
+ "model": { "const": "gpt-5.4" }
19
+ }
20
+ }
21
+ ]
22
+ }
23
+ ]
24
+ }
@@ -0,0 +1,24 @@
1
+ {
2
+ "kind": "test-linter-fix-flow",
3
+ "version": 1,
4
+ "phases": [
5
+ {
6
+ "id": "test-linter-fix",
7
+ "steps": [
8
+ {
9
+ "id": "run_codex_test_linter_fix",
10
+ "node": "codex-local-prompt",
11
+ "prompt": {
12
+ "templateRef": "test-linter-fix",
13
+ "extraPrompt": { "ref": "params.extraPrompt" },
14
+ "format": "task-prompt"
15
+ },
16
+ "params": {
17
+ "labelText": { "const": "Running Codex test-linter-fix mode locally" },
18
+ "model": { "const": "gpt-5.4" }
19
+ }
20
+ }
21
+ ]
22
+ }
23
+ ]
24
+ }
@@ -0,0 +1,19 @@
1
+ {
2
+ "kind": "test-flow",
3
+ "version": 1,
4
+ "phases": [
5
+ {
6
+ "id": "test",
7
+ "steps": [
8
+ {
9
+ "id": "verify_build",
10
+ "node": "verify-build",
11
+ "params": {
12
+ "dockerComposeFile": { "ref": "params.dockerComposeFile" },
13
+ "labelText": { "const": "Running build verification in isolated Docker" }
14
+ }
15
+ }
16
+ ]
17
+ }
18
+ ]
19
+ }
@@ -1,6 +1,6 @@
1
1
  import { runFlow } from "../flow-runner.js";
2
2
  import { runNode } from "../node-runner.js";
3
- import { codexDockerPromptNode } from "../nodes/codex-docker-prompt-node.js";
3
+ import { codexLocalPromptNode } from "../nodes/codex-local-prompt-node.js";
4
4
  import { verifyBuildNode } from "../nodes/verify-build-node.js";
5
5
  export const implementFlowDefinition = {
6
6
  kind: "implement-flow",
@@ -9,10 +9,9 @@ export const implementFlowDefinition = {
9
9
  {
10
10
  id: "run_codex_implement",
11
11
  async run(context, params) {
12
- await runNode(codexDockerPromptNode, context, {
13
- dockerComposeFile: params.dockerComposeFile,
12
+ await runNode(codexLocalPromptNode, context, {
14
13
  prompt: params.prompt,
15
- labelText: "Running Codex implementation mode in isolated Docker",
14
+ labelText: "Running Codex implementation mode locally",
16
15
  });
17
16
  return { completed: true };
18
17
  },
@@ -1,59 +1,19 @@
1
- import { existsSync, readFileSync } from "node:fs";
2
- import { taskSummaryFile } from "../../artifacts.js";
3
- import { runFlow } from "../flow-runner.js";
4
- import { runNode } from "../node-runner.js";
5
- import { commandCheckNode } from "../nodes/command-check-node.js";
6
- import { jiraFetchNode } from "../nodes/jira-fetch-node.js";
7
- import { taskSummaryNode } from "../nodes/task-summary-node.js";
8
- export const preflightFlowDefinition = {
9
- kind: "interactive-preflight-flow",
10
- version: 1,
11
- steps: [
12
- {
13
- id: "check_commands",
14
- async run(context) {
15
- const result = await runNode(commandCheckNode, context, {
16
- commands: [
17
- { commandName: "codex", envVarName: "CODEX_BIN" },
18
- { commandName: "claude", envVarName: "CLAUDE_BIN" },
19
- ],
20
- });
21
- return { completed: true, metadata: { resolved: result.value.resolved.length } };
22
- },
23
- },
24
- {
25
- id: "fetch_jira_if_needed",
26
- async run(context, params) {
27
- if (!params.forceRefresh && existsSync(params.jiraTaskFile)) {
28
- return { completed: true, metadata: { skipped: true } };
29
- }
30
- await runNode(jiraFetchNode, context, {
31
- jiraApiUrl: params.jiraApiUrl,
32
- outputFile: params.jiraTaskFile,
33
- });
34
- return { completed: true };
35
- },
36
- },
37
- {
38
- id: "load_or_generate_task_summary",
39
- async run(context, params) {
40
- const summaryPath = taskSummaryFile(params.taskKey);
41
- if (!params.forceRefresh && existsSync(params.jiraTaskFile) && existsSync(summaryPath)) {
42
- context.setSummary?.(readFileSync(summaryPath, "utf8").trim());
43
- return { completed: true, metadata: { source: "existing" } };
44
- }
45
- const claudeCmd = context.runtime.resolveCmd("claude", "CLAUDE_BIN");
46
- await runNode(taskSummaryNode, context, {
47
- jiraTaskFile: params.jiraTaskFile,
48
- taskKey: params.taskKey,
49
- claudeCmd,
50
- verbose: context.verbose,
51
- });
52
- return { completed: true, metadata: { source: "generated" } };
53
- },
54
- },
55
- ],
56
- };
1
+ import { loadDeclarativeFlow } from "../declarative-flows.js";
2
+ import { runExpandedPhase } from "../declarative-flow-runner.js";
57
3
  export async function runPreflightFlow(context, params) {
58
- await runFlow(preflightFlowDefinition, context, params);
4
+ const flow = loadDeclarativeFlow("preflight.json");
5
+ const executionState = {
6
+ flowKind: flow.kind,
7
+ flowVersion: flow.version,
8
+ terminated: false,
9
+ phases: [],
10
+ };
11
+ for (const phase of flow.phases) {
12
+ await runExpandedPhase(phase, context, params, flow.constants, {
13
+ executionState,
14
+ flowKind: flow.kind,
15
+ flowVersion: flow.version,
16
+ });
17
+ }
18
+ return executionState;
59
19
  }
@@ -3,7 +3,7 @@ import { TaskRunnerError } from "../../errors.js";
3
3
  import { REVIEW_FIX_PROMPT_TEMPLATE, formatPrompt, formatTemplate } from "../../prompts.js";
4
4
  import { runFlow } from "../flow-runner.js";
5
5
  import { runNode } from "../node-runner.js";
6
- import { codexDockerPromptNode } from "../nodes/codex-docker-prompt-node.js";
6
+ import { codexLocalPromptNode } from "../nodes/codex-local-prompt-node.js";
7
7
  import { verifyBuildNode } from "../nodes/verify-build-node.js";
8
8
  export function createReviewFixFlowDefinition(iteration) {
9
9
  return {
@@ -20,10 +20,9 @@ export function createReviewFixFlowDefinition(iteration) {
20
20
  items: stepParams.reviewFixPoints ?? "",
21
21
  review_fix_file: reviewFixFile,
22
22
  }), stepParams.extraPrompt);
23
- await runNode(codexDockerPromptNode, stepContext, {
24
- dockerComposeFile: stepParams.dockerComposeFile,
23
+ await runNode(codexLocalPromptNode, stepContext, {
25
24
  prompt,
26
- labelText: `Running Codex review-fix mode in isolated Docker (iteration ${iteration})`,
25
+ labelText: `Running Codex review-fix mode locally (iteration ${iteration})`,
27
26
  requiredArtifacts: stepContext.dryRun ? [] : [reviewFixFile],
28
27
  missingArtifactsMessage: "Review-fix mode did not produce the required review-fix artifact.",
29
28
  });
@@ -1,5 +1,5 @@
1
1
  import { existsSync, readdirSync } from "node:fs";
2
- import { READY_TO_MERGE_FILE, REVIEW_REPLY_FILE_RE, artifactFile, planArtifacts, requireArtifacts, } from "../../artifacts.js";
2
+ import { REVIEW_REPLY_FILE_RE, artifactFile, planArtifacts, readyToMergeFile, requireArtifacts, taskWorkspaceDir, } from "../../artifacts.js";
3
3
  import { REVIEW_REPLY_SUMMARY_PROMPT_TEMPLATE, REVIEW_SUMMARY_PROMPT_TEMPLATE, formatTemplate } from "../../prompts.js";
4
4
  import { printPanel } from "../../tui.js";
5
5
  import { runFlow } from "../flow-runner.js";
@@ -9,7 +9,11 @@ import { reviewClaudeNode } from "../nodes/review-claude-node.js";
9
9
  import { reviewReplyCodexNode } from "../nodes/review-reply-codex-node.js";
10
10
  function nextReviewIterationForTask(taskKey) {
11
11
  let maxIndex = 0;
12
- for (const entry of readdirSync(process.cwd(), { withFileTypes: true })) {
12
+ const workspaceDir = taskWorkspaceDir(taskKey);
13
+ if (!existsSync(workspaceDir)) {
14
+ return 1;
15
+ }
16
+ for (const entry of readdirSync(workspaceDir, { withFileTypes: true })) {
13
17
  if (!entry.isFile()) {
14
18
  continue;
15
19
  }
@@ -96,8 +100,8 @@ export function createReviewFlowDefinition(iteration) {
96
100
  },
97
101
  {
98
102
  id: "check_ready_to_merge",
99
- async run(stepContext) {
100
- const readyToMerge = !stepContext.dryRun && existsSync(READY_TO_MERGE_FILE);
103
+ async run(stepContext, stepParams) {
104
+ const readyToMerge = !stepContext.dryRun && existsSync(readyToMergeFile(stepParams.taskKey));
101
105
  if (readyToMerge) {
102
106
  printPanel("Ready To Merge", "Изменения готовы к merge\nФайл ready-to-merge.md создан.", "green");
103
107
  }
@@ -1,13 +1,12 @@
1
1
  import { planArtifacts, requireArtifacts } from "../../artifacts.js";
2
2
  import { TEST_FIX_PROMPT_TEMPLATE, TEST_LINTER_FIX_PROMPT_TEMPLATE, formatPrompt } from "../../prompts.js";
3
3
  import { runNode } from "../node-runner.js";
4
- import { codexDockerPromptNode } from "../nodes/codex-docker-prompt-node.js";
4
+ import { codexLocalPromptNode } from "../nodes/codex-local-prompt-node.js";
5
5
  export async function runTestFixFlow(context, params) {
6
6
  requireArtifacts(planArtifacts(params.taskKey), `${params.command} mode requires plan artifacts from the planning phase.`);
7
7
  const prompt = formatPrompt(params.command === "test-fix" ? TEST_FIX_PROMPT_TEMPLATE : TEST_LINTER_FIX_PROMPT_TEMPLATE, params.extraPrompt);
8
- await runNode(codexDockerPromptNode, context, {
9
- dockerComposeFile: params.dockerComposeFile,
8
+ await runNode(codexLocalPromptNode, context, {
10
9
  prompt,
11
- labelText: `Running Codex ${params.command} mode in isolated Docker`,
10
+ labelText: `Running Codex ${params.command} mode locally`,
12
11
  });
13
12
  }