@oisincoveney/pipeline 2.8.4 → 2.9.0
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/.agents/skills/orchestrate/SKILL.md +45 -32
- package/README.md +51 -41
- package/defaults/profiles.yaml +1 -1
- package/dist/argo-submit.js +1 -1
- package/dist/cli/doctor.d.ts +21 -0
- package/dist/cli/doctor.js +268 -0
- package/dist/cli/format.js +6 -3
- package/dist/cli/program.d.ts +14 -16
- package/dist/cli/program.js +291 -104
- package/dist/cli/run-resolver.js +58 -0
- package/dist/commands/bench-command.js +12 -4
- package/dist/commands/pipeline-command.js +22 -5
- package/dist/commands/runner-command-command.js +32 -9
- package/dist/config/lint.js +44 -26
- package/dist/context/repo-map.js +72 -56
- package/dist/gates.js +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +20 -14
- package/dist/install-commands/claude-code.js +4 -33
- package/dist/install-commands/opencode.js +119 -171
- package/dist/mcp/repo-local-backends.js +51 -39
- package/dist/moka-submit.d.ts +6 -6
- package/dist/moka-submit.js +3 -3
- package/dist/pipeline-runtime.js +15 -5
- package/dist/planning/generate.js +2 -2
- package/dist/run-control/commands.js +340 -0
- package/dist/run-control/contracts.d.ts +21 -0
- package/dist/run-control/contracts.js +129 -0
- package/dist/run-control/detach.js +79 -0
- package/dist/run-control/runtime-reporter.js +187 -0
- package/dist/run-control/store.js +304 -0
- package/dist/run-control/supervisor.js +192 -0
- package/dist/runner-command/finalize.js +28 -37
- package/dist/runner-command/lifecycle-context.js +130 -63
- package/dist/runner-command/lifecycle.js +22 -31
- package/dist/runner-command/run.js +120 -72
- package/dist/runner-command/task-descriptor.js +11 -4
- package/dist/runner-event-schema.d.ts +6 -6
- package/dist/runner.js +1 -1
- package/dist/runtime/agent-node/agent-node.js +3 -3
- package/dist/runtime/builtins/builtins.js +1 -1
- package/dist/runtime/changed-files/changed-files.js +1 -1
- package/dist/runtime/context/context.js +1 -1
- package/dist/runtime/contracts/contracts.d.ts +4 -0
- package/dist/runtime/hooks/hooks.js +1 -1
- package/dist/runtime/json-validation/json-validation.js +49 -23
- package/dist/runtime/local-scheduler.js +49 -26
- package/dist/runtime/opencode-adapter.js +14 -10
- package/dist/runtime/opencode-runtime.js +22 -20
- package/dist/runtime/opencode-session-executor.js +1 -1
- package/dist/runtime/parallel-node/parallel-node.js +10 -0
- package/dist/runtime/run-journal.js +17 -10
- package/dist/runtime/services/file-system-service.js +29 -0
- package/dist/runtime/services/opencode-runtime-server-service.js +27 -0
- package/dist/runtime/services/repo-io-service.js +48 -0
- package/dist/runtime/services/run-journal-file-service.js +20 -0
- package/dist/runtime/services/runner-command-io-service.js +88 -0
- package/dist/runtime/workflow-lifecycle.js +76 -39
- package/dist/schedule/backlog-context.js +55 -29
- package/docs/operator-guide.md +73 -32
- package/package.json +1 -1
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { DEFAULT_OPENCODE_ECOSYSTEM_MANIFEST } from "../config/defaults.js";
|
|
2
2
|
import { resolvePackageAssetPath } from "../package-assets.js";
|
|
3
3
|
import "../config.js";
|
|
4
|
-
import {
|
|
5
|
-
import { mergeOpenCodeProjectConfig } from "../opencode-project-config.js";
|
|
4
|
+
import { RepoIoService, runRepoIoSync } from "../runtime/services/repo-io-service.js";
|
|
6
5
|
import { renderOpenCodeGatewayConfig } from "../mcp/gateway.js";
|
|
6
|
+
import { compileWorkflowPlan } from "../planning/compile.js";
|
|
7
7
|
import { opencodeAgentName } from "../runtime/opencode-agent-name.js";
|
|
8
|
+
import { mergeOpenCodeProjectConfig } from "../opencode-project-config.js";
|
|
8
9
|
import { AGENTS_MD_END, AGENTS_MD_START, COMMAND_HOSTS, GENERATED_MARKER, GENERATED_TS_MARKER, OPENCODE_PROJECT_CONFIG_PATH, OWNER_MARKER_PREFIX, OWNER_TS_MARKER_PREFIX, SINGLE_OPENCODE_PLUGIN_ARRAY_RE, commandIdForHost, compactLines, entrypointDescription, entrypointEntries, instructionsPointer, invocationForHost, profileEntries } from "./shared.js";
|
|
9
|
-
import {
|
|
10
|
+
import { Effect } from "effect";
|
|
10
11
|
import { basename } from "node:path";
|
|
11
12
|
import matter from "gray-matter";
|
|
12
13
|
//#region src/install-commands/opencode.ts
|
|
@@ -116,110 +117,48 @@ function orchestratorBlock(config) {
|
|
|
116
117
|
instructionsPointer(profile)
|
|
117
118
|
].join("\n");
|
|
118
119
|
}
|
|
119
|
-
function
|
|
120
|
-
const routes = agentDispatchRoutes(host, config, workflowId);
|
|
121
|
-
if (routes.length === 0) return;
|
|
122
|
-
const plan = compileWorkflowPlan(config, workflowId);
|
|
123
|
-
const nativeRoutes = routes.filter((route) => route.kind !== "cli");
|
|
124
|
-
const cliRoutes = routes.filter((route) => route.kind === "cli");
|
|
125
|
-
return [
|
|
126
|
-
`Run workflow \`${plan.workflowId}\` for the user task.`,
|
|
127
|
-
"",
|
|
128
|
-
nativeDispatchBlock(host, nativeRoutes),
|
|
129
|
-
cliDispatchBlock(host, cliRoutes),
|
|
130
|
-
nodePromptContract(plan.workflowId, routes),
|
|
131
|
-
"Only package-configured gates are blocking. Do not invent RED, GREEN, full-suite, typecheck, or unrelated-drift gates.",
|
|
132
|
-
"If a node returns targeted evidence and has no configured blocking gate, advance to the next node.",
|
|
133
|
-
"Do not bypass configured runner subprocesses or package-configured gates when executing nodes.",
|
|
134
|
-
"Use the listed Task tool routes for native nodes, and run nodes with satisfied dependencies in parallel whenever the host supports concurrent subagent work.",
|
|
135
|
-
hostSpecificDispatchGuard(host, nativeRoutes, cliRoutes)
|
|
136
|
-
].filter((line) => Boolean(line)).join("\n");
|
|
137
|
-
}
|
|
138
|
-
function entrypointDispatchBlock(host, config, id, entrypoint) {
|
|
139
|
-
if ("workflow" in entrypoint) return dispatchBlock(host, config, entrypoint.workflow);
|
|
120
|
+
function entrypointDispatchBlock(_host, _config, id, entrypoint) {
|
|
140
121
|
return [
|
|
141
|
-
`
|
|
142
|
-
`
|
|
143
|
-
|
|
144
|
-
"The
|
|
145
|
-
"
|
|
146
|
-
"Use `moka submit --schedule <schedule.yaml> <task description>` only when rerunning an existing schedule artifact."
|
|
122
|
+
`Run \`${canonicalLocalRunCommand(id, entrypoint)}\` for local supervised execution.`,
|
|
123
|
+
`Configured entrypoint target: ${entrypointTargetId(entrypoint)}.`,
|
|
124
|
+
"This compatibility slash command delegates to the canonical `moka run` supervisor instead of reimplementing orchestration in the host.",
|
|
125
|
+
"The supervisor owns schedule generation, node execution, run state, and configured gates.",
|
|
126
|
+
"Keep reporting clear that this path is CLI/supervised runtime, not host-native Task execution."
|
|
147
127
|
].join("\n");
|
|
148
128
|
}
|
|
149
|
-
function
|
|
150
|
-
|
|
151
|
-
|
|
129
|
+
function entrypointTargetId(entrypoint) {
|
|
130
|
+
return "workflow" in entrypoint ? entrypoint.workflow : entrypoint.schedule;
|
|
131
|
+
}
|
|
132
|
+
function canonicalLocalRunCommand(id, entrypoint) {
|
|
133
|
+
return [
|
|
134
|
+
"moka",
|
|
135
|
+
"run",
|
|
136
|
+
...canonicalLocalRunFlags(id, entrypoint),
|
|
137
|
+
"<task description>"
|
|
138
|
+
].join(" ");
|
|
139
|
+
}
|
|
140
|
+
function canonicalLocalRunFlags(id, entrypoint) {
|
|
141
|
+
if (id === "quick") return ["--effort", "quick"];
|
|
142
|
+
if (id === "execute") return ["--effort", "thorough"];
|
|
143
|
+
if (id === "inspect") return ["--read-only"];
|
|
144
|
+
if ("workflow" in entrypoint) return ["--workflow", entrypoint.workflow];
|
|
145
|
+
return ["--entrypoint", id];
|
|
152
146
|
}
|
|
153
147
|
function localRosterAgentIds(config) {
|
|
154
148
|
return nativeProfileEntries("opencode", config).map(([id]) => nativeAgentIdForHost("opencode", id));
|
|
155
149
|
}
|
|
156
150
|
function localOrchestratorDispatchBlock(config) {
|
|
157
151
|
return [
|
|
158
|
-
"Orchestrate
|
|
159
|
-
"
|
|
152
|
+
"Orchestrate through the canonical local `moka run` supervisor. Load and follow the `orchestrate` skill.",
|
|
153
|
+
"For compatibility slash commands, run the `moka run` command and flags shown in the command body.",
|
|
154
|
+
"Treat execution as CLI/supervised runtime, not OpenCode-native Task execution.",
|
|
160
155
|
"",
|
|
161
|
-
"
|
|
156
|
+
"Configured roster:",
|
|
162
157
|
...localRosterAgentIds(config).map((id) => `- ${id}`),
|
|
163
158
|
"",
|
|
164
|
-
"
|
|
165
|
-
].join("\n");
|
|
166
|
-
}
|
|
167
|
-
function nativeDispatchBlock(host, routes) {
|
|
168
|
-
if (routes.length === 0) return;
|
|
169
|
-
return [
|
|
170
|
-
`${hostDisplayName(host)} native routes:`,
|
|
171
|
-
...routes.map(nativeDispatchLine),
|
|
172
|
-
""
|
|
159
|
+
"Report the supervisor's evidence and configured-gate results; do not invent extra gates."
|
|
173
160
|
].join("\n");
|
|
174
161
|
}
|
|
175
|
-
function nativeDispatchLine(route) {
|
|
176
|
-
const needs = needsSummary(route.needs);
|
|
177
|
-
const model = route.model ? ` model=${route.model}` : "";
|
|
178
|
-
return `- ${route.nodeId}: Task tool subagent_type=${route.nativeAgentId}${model} runner=${route.runnerId} needs=${needs}`;
|
|
179
|
-
}
|
|
180
|
-
function cliDispatchBlock(host, routes) {
|
|
181
|
-
if (routes.length === 0) return;
|
|
182
|
-
return [
|
|
183
|
-
`These nodes are not ${hostDisplayName(host)} native routes.`,
|
|
184
|
-
"CLI routes:",
|
|
185
|
-
...routes.map(cliDispatchLine),
|
|
186
|
-
""
|
|
187
|
-
].join("\n");
|
|
188
|
-
}
|
|
189
|
-
function cliDispatchLine(route) {
|
|
190
|
-
return `- ${route.nodeId}: ${route.runnerId} CLI profile=${route.profileId} command=\`${runnerCliCommand(route)}\` needs=${needsSummary(route.needs)}`;
|
|
191
|
-
}
|
|
192
|
-
function runnerCliCommand(route) {
|
|
193
|
-
if (route.runnerId === "opencode") return `opencode run --agent "${opencodeAgentName(route.profileId)}" --format json --dir <repo-root> <node prompt>`;
|
|
194
|
-
throw new Error(`runner '${route.runnerId}' cannot be represented as a supported native or CLI route`);
|
|
195
|
-
}
|
|
196
|
-
function nodePromptContract(workflowId, routes) {
|
|
197
|
-
return [
|
|
198
|
-
routes.some((route) => route.kind === "cli") ? "For each CLI node prompt include:" : "For each native node prompt include:",
|
|
199
|
-
"- user task",
|
|
200
|
-
`- workflow id: ${workflowId}`,
|
|
201
|
-
"- node id",
|
|
202
|
-
"- profile id",
|
|
203
|
-
"- runner id",
|
|
204
|
-
"- profile instructions reference",
|
|
205
|
-
"- profile grants",
|
|
206
|
-
"- dependency outputs",
|
|
207
|
-
""
|
|
208
|
-
].join("\n");
|
|
209
|
-
}
|
|
210
|
-
function hostSpecificDispatchGuard(host, nativeRoutes, cliRoutes) {
|
|
211
|
-
if (cliRoutes.length > 0 && nativeRoutes.length > 0) return `Do not claim CLI routes are ${hostDisplayName(host)} native routes.`;
|
|
212
|
-
if (cliRoutes.length > 0 && nativeRoutes.length === 0) return `Do not claim these nodes are ${hostDisplayName(host)} subagents.`;
|
|
213
|
-
}
|
|
214
|
-
function hostDisplayName(host) {
|
|
215
|
-
return {
|
|
216
|
-
opencode: "OpenCode",
|
|
217
|
-
"claude-code": "Claude Code"
|
|
218
|
-
}[host];
|
|
219
|
-
}
|
|
220
|
-
function needsSummary(needs) {
|
|
221
|
-
return needs.length > 0 ? needs.join(",") : "none";
|
|
222
|
-
}
|
|
223
162
|
const OPENCODE_PERMISSION_TOOLS = [
|
|
224
163
|
"bash",
|
|
225
164
|
"edit",
|
|
@@ -293,10 +232,17 @@ function npmPluginPackage(item) {
|
|
|
293
232
|
function formatOpenCodeProjectJson(value) {
|
|
294
233
|
return `${JSON.stringify(value, null, 2).replace(SINGLE_OPENCODE_PLUGIN_ARRAY_RE, "\n \"plugin\": [$1]")}\n`;
|
|
295
234
|
}
|
|
296
|
-
function
|
|
297
|
-
return
|
|
298
|
-
|
|
299
|
-
|
|
235
|
+
function localPluginDefinitionsEffect() {
|
|
236
|
+
return Effect.gen(function* () {
|
|
237
|
+
return (yield* Effect.all(DEFAULT_OPENCODE_ECOSYSTEM_MANIFEST.ecosystem_code.map(localPluginDefinitionEffect))).flat();
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
function localPluginDefinitionEffect(item) {
|
|
241
|
+
const pluginConfig = item.plugin;
|
|
242
|
+
if (pluginConfig?.kind !== "local") return Effect.succeed([]);
|
|
243
|
+
const source = resolvePackageAssetPath(pluginConfig.source_path);
|
|
244
|
+
return Effect.gen(function* () {
|
|
245
|
+
const plugin = (yield* (yield* RepoIoService).readText(source)).trimEnd();
|
|
300
246
|
return [{
|
|
301
247
|
content: [
|
|
302
248
|
GENERATED_TS_MARKER,
|
|
@@ -307,80 +253,81 @@ function localPluginDefinitions() {
|
|
|
307
253
|
].join("\n"),
|
|
308
254
|
host: "opencode",
|
|
309
255
|
invocation: invocationForHost("opencode"),
|
|
310
|
-
path:
|
|
256
|
+
path: pluginConfig.target_path
|
|
311
257
|
}];
|
|
312
258
|
});
|
|
313
259
|
}
|
|
314
|
-
function
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
260
|
+
function opencodeDefinitionsEffect(config, cwd) {
|
|
261
|
+
return Effect.gen(function* () {
|
|
262
|
+
const orchestrator = orchestratorProfile(config);
|
|
263
|
+
const pluginDefinitions = yield* localPluginDefinitionsEffect();
|
|
264
|
+
return [
|
|
265
|
+
...entrypointCommandDefinitions("opencode", config, (id, entrypoint) => ({
|
|
266
|
+
content: markdown({
|
|
267
|
+
...orchestrator ? { agent: OPENCODE_ORCHESTRATOR_AGENT_ID } : {},
|
|
268
|
+
description: entrypointDescription(id, entrypoint)
|
|
269
|
+
}, compactLines([
|
|
270
|
+
header("opencode").trimEnd(),
|
|
271
|
+
"",
|
|
272
|
+
`Invoke this command with \`${invocationForHost("opencode", id)}\`.`,
|
|
273
|
+
"",
|
|
274
|
+
orchestratorBlock(config),
|
|
275
|
+
"",
|
|
276
|
+
entrypointDispatchBlock("opencode", config, id, entrypoint)
|
|
277
|
+
]).join("\n")),
|
|
278
|
+
host: "opencode",
|
|
279
|
+
invocation: invocationForHost("opencode", id),
|
|
280
|
+
path: `.opencode/commands/${commandIdForHost("opencode", id)}.md`
|
|
281
|
+
})),
|
|
282
|
+
{
|
|
283
|
+
content: renderOpenCodeProjectConfig(config),
|
|
284
|
+
host: "opencode",
|
|
285
|
+
invocation: invocationForHost("opencode"),
|
|
286
|
+
path: ".opencode/opencode.json"
|
|
287
|
+
},
|
|
288
|
+
...orchestrator ? [{
|
|
289
|
+
content: markdown({
|
|
290
|
+
description: "Orchestrate the configured pipeline and enforce gates.",
|
|
291
|
+
mode: "primary",
|
|
292
|
+
name: OPENCODE_ORCHESTRATOR_AGENT_ID,
|
|
293
|
+
permission: opencodePermission(orchestrator, { allowedTaskAgents: localRosterAgentIds(config) })
|
|
294
|
+
}, compactLines([
|
|
295
|
+
header("opencode").trimEnd(),
|
|
296
|
+
"",
|
|
297
|
+
orchestratorBlock(config),
|
|
298
|
+
"",
|
|
299
|
+
localOrchestratorDispatchBlock(config)
|
|
300
|
+
]).join("\n")),
|
|
301
|
+
host: "opencode",
|
|
302
|
+
invocation: invocationForHost("opencode"),
|
|
303
|
+
path: `.opencode/agents/${OPENCODE_ORCHESTRATOR_AGENT_ID}.md`
|
|
304
|
+
}] : [],
|
|
305
|
+
...nativeProfileEntries("opencode", config).map(([id, profile]) => ({
|
|
306
|
+
content: markdown({
|
|
307
|
+
name: nativeAgentIdForHost("opencode", id),
|
|
308
|
+
description: profile.description ?? id,
|
|
309
|
+
hidden: false,
|
|
310
|
+
mode: "all",
|
|
311
|
+
...opencodeModelProjection(config, profile),
|
|
312
|
+
permission: opencodePermission(profile)
|
|
313
|
+
}, [
|
|
314
|
+
header("opencode").trimEnd(),
|
|
315
|
+
"",
|
|
316
|
+
profile.description ?? id,
|
|
317
|
+
"",
|
|
318
|
+
"Configured grants:",
|
|
319
|
+
grants(profile),
|
|
320
|
+
"",
|
|
321
|
+
instructionsPointer(profile)
|
|
322
|
+
].join("\n")),
|
|
323
|
+
host: "opencode",
|
|
324
|
+
invocation: invocationForHost("opencode"),
|
|
325
|
+
path: `.opencode/agents/${nativeAgentIdForHost("opencode", id)}.md`
|
|
326
|
+
})),
|
|
327
|
+
...pluginDefinitions,
|
|
328
|
+
projectAgentsMdDefinition(cwd, "opencode")
|
|
329
|
+
];
|
|
330
|
+
});
|
|
384
331
|
}
|
|
385
332
|
function projectAgentsMdDefinition(cwd, host) {
|
|
386
333
|
const repoName = basename(cwd);
|
|
@@ -398,7 +345,8 @@ function projectAgentsMdDefinition(cwd, host) {
|
|
|
398
345
|
"",
|
|
399
346
|
"This repository uses package-owned `@oisincoveney/pipeline` config.",
|
|
400
347
|
"",
|
|
401
|
-
"- Use
|
|
348
|
+
"- Use `moka run \"<task>\"` first for local supervised execution from the package-owned pipeline config.",
|
|
349
|
+
"- Use `/moka-quick`, `/moka-execute`, or `/moka-inspect` as compatibility slash-command entrypoints when available.",
|
|
402
350
|
"- Load and follow the relevant skill from `.agents/skills` before doing specialized work.",
|
|
403
351
|
"- Prefer the package-defined pipeline profiles and generated command surfaces over ad hoc subagent prompts.",
|
|
404
352
|
"- When the user needs to run a command, copy the command into the clipboard and tell the user what needs to be returned.",
|
|
@@ -436,7 +384,7 @@ const opencodeAdapter = {
|
|
|
436
384
|
".opencode/skills"
|
|
437
385
|
],
|
|
438
386
|
definitions(config, cwd) {
|
|
439
|
-
return
|
|
387
|
+
return runRepoIoSync(opencodeDefinitionsEffect(config, cwd));
|
|
440
388
|
},
|
|
441
389
|
mergeDefinition(definition, existingContent) {
|
|
442
390
|
if (definition.path !== ".opencode/opencode.json") return;
|
|
@@ -455,4 +403,4 @@ const opencodeAdapter = {
|
|
|
455
403
|
}
|
|
456
404
|
};
|
|
457
405
|
//#endregion
|
|
458
|
-
export { agentDispatchRoutes, entrypointDispatchBlock, grants, header, markdown, opencodeAdapter, projectAgentsMdDefinition, resolvedHostModel
|
|
406
|
+
export { agentDispatchRoutes, entrypointDispatchBlock, grants, header, markdown, opencodeAdapter, projectAgentsMdDefinition, resolvedHostModel };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { RepoIoService, runRepoIoSync } from "../runtime/services/repo-io-service.js";
|
|
2
|
+
import { Effect } from "effect";
|
|
2
3
|
import { join } from "node:path";
|
|
3
4
|
//#region src/mcp/repo-local-backends.ts
|
|
4
5
|
const BACKEND_TEMPLATES = {
|
|
@@ -23,45 +24,56 @@ const BACKEND_TEMPLATES = {
|
|
|
23
24
|
}
|
|
24
25
|
};
|
|
25
26
|
function resolveRepoLocalBackendSpecs(config, options) {
|
|
26
|
-
|
|
27
|
-
if (!gateway) return [];
|
|
28
|
-
const exists = options.exists ?? existsSync;
|
|
29
|
-
return Object.entries(gateway.backends).filter(([, backend]) => backend.locality === "repo-local").map(([id, backend]) => repoLocalBackendSpec(id, backend, {
|
|
30
|
-
cwd: options.cwd,
|
|
31
|
-
env: options.env ?? process.env,
|
|
32
|
-
exists
|
|
33
|
-
}));
|
|
27
|
+
return runRepoIoSync(resolveRepoLocalBackendSpecsEffect(config, options));
|
|
34
28
|
}
|
|
35
|
-
function
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
29
|
+
function resolveRepoLocalBackendSpecsEffect(config, options) {
|
|
30
|
+
return Effect.gen(function* () {
|
|
31
|
+
const gateway = config.mcp_gateway;
|
|
32
|
+
if (!gateway) return [];
|
|
33
|
+
return yield* Effect.all(Object.entries(gateway.backends).filter(([, backend]) => backend.locality === "repo-local").map(([id, backend]) => repoLocalBackendSpecEffect(id, backend, {
|
|
34
|
+
cwd: options.cwd,
|
|
35
|
+
env: options.env ?? process.env,
|
|
36
|
+
exists: options.exists
|
|
37
|
+
})));
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
function repoLocalBackendSpecEffect(id, backend, options) {
|
|
41
|
+
return Effect.gen(function* () {
|
|
42
|
+
const workspacePath = workspacePathForBackend(backend, options);
|
|
43
|
+
const template = BACKEND_TEMPLATES[id] ?? {
|
|
44
|
+
args: () => [],
|
|
45
|
+
command: id,
|
|
46
|
+
requiredPath: "."
|
|
47
|
+
};
|
|
48
|
+
const ready = yield* backendPathExists(join(workspacePath, template.requiredPath), options.exists);
|
|
49
|
+
const readiness = ready ? { ok: true } : {
|
|
50
|
+
ok: false,
|
|
51
|
+
reason: `Missing ${template.requiredPath} in ${workspacePath}`
|
|
52
|
+
};
|
|
53
|
+
const enabled = ready || backend.required;
|
|
54
|
+
return {
|
|
55
|
+
args: template.args(workspacePath),
|
|
56
|
+
command: template.command,
|
|
57
|
+
cwd: workspacePath,
|
|
58
|
+
enabled,
|
|
59
|
+
env: { PIPELINE_TARGET_PATH: workspacePath },
|
|
60
|
+
id,
|
|
61
|
+
mount: {
|
|
62
|
+
containerPath: "/workspace",
|
|
63
|
+
hostPath: workspacePath
|
|
64
|
+
},
|
|
65
|
+
readiness,
|
|
66
|
+
required: backend.required,
|
|
67
|
+
toolPrefixes: backend.tool_prefixes,
|
|
68
|
+
workspacePath
|
|
69
|
+
};
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
function backendPathExists(path, exists) {
|
|
73
|
+
if (exists) return Effect.sync(() => exists(path));
|
|
74
|
+
return Effect.gen(function* () {
|
|
75
|
+
return yield* (yield* RepoIoService).exists(path);
|
|
76
|
+
});
|
|
65
77
|
}
|
|
66
78
|
function workspacePathForBackend(backend, options) {
|
|
67
79
|
return backend.workspace_path_source === "PIPELINE_TARGET_PATH" ? options.env.PIPELINE_TARGET_PATH || options.cwd : options.cwd;
|
package/dist/moka-submit.d.ts
CHANGED
|
@@ -5,13 +5,13 @@ import { z } from "zod";
|
|
|
5
5
|
//#region src/moka-submit.d.ts
|
|
6
6
|
declare const mokaSubmitDirectHooksSchema: z.ZodRecord<z.ZodEnum<{
|
|
7
7
|
"workflow.start": "workflow.start";
|
|
8
|
+
"node.finish": "node.finish";
|
|
9
|
+
"node.start": "node.start";
|
|
8
10
|
"workflow.success": "workflow.success";
|
|
9
11
|
"workflow.failure": "workflow.failure";
|
|
10
12
|
"workflow.complete": "workflow.complete";
|
|
11
|
-
"node.start": "node.start";
|
|
12
13
|
"node.success": "node.success";
|
|
13
14
|
"node.error": "node.error";
|
|
14
|
-
"node.finish": "node.finish";
|
|
15
15
|
"gate.failure": "gate.failure";
|
|
16
16
|
}> & z.core.$partial, z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
17
17
|
failure: z.ZodDefault<z.ZodEnum<{
|
|
@@ -94,13 +94,13 @@ declare const mokaSubmitOptionsSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
94
94
|
}, z.core.$strict>>;
|
|
95
95
|
hooks: z.ZodOptional<z.ZodRecord<z.ZodEnum<{
|
|
96
96
|
"workflow.start": "workflow.start";
|
|
97
|
+
"node.finish": "node.finish";
|
|
98
|
+
"node.start": "node.start";
|
|
97
99
|
"workflow.success": "workflow.success";
|
|
98
100
|
"workflow.failure": "workflow.failure";
|
|
99
101
|
"workflow.complete": "workflow.complete";
|
|
100
|
-
"node.start": "node.start";
|
|
101
102
|
"node.success": "node.success";
|
|
102
103
|
"node.error": "node.error";
|
|
103
|
-
"node.finish": "node.finish";
|
|
104
104
|
"gate.failure": "gate.failure";
|
|
105
105
|
}> & z.core.$partial, z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
106
106
|
failure: z.ZodDefault<z.ZodEnum<{
|
|
@@ -206,13 +206,13 @@ declare const mokaSubmitOptionsSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
206
206
|
}, z.core.$strict>>;
|
|
207
207
|
hooks: z.ZodOptional<z.ZodRecord<z.ZodEnum<{
|
|
208
208
|
"workflow.start": "workflow.start";
|
|
209
|
+
"node.finish": "node.finish";
|
|
210
|
+
"node.start": "node.start";
|
|
209
211
|
"workflow.success": "workflow.success";
|
|
210
212
|
"workflow.failure": "workflow.failure";
|
|
211
213
|
"workflow.complete": "workflow.complete";
|
|
212
|
-
"node.start": "node.start";
|
|
213
214
|
"node.success": "node.success";
|
|
214
215
|
"node.error": "node.error";
|
|
215
|
-
"node.finish": "node.finish";
|
|
216
216
|
"gate.failure": "gate.failure";
|
|
217
217
|
}> & z.core.$partial, z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
218
218
|
failure: z.ZodDefault<z.ZodEnum<{
|
package/dist/moka-submit.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
+
import { buildRunnerCommandPayload, runnerDeliverySchema, runnerHookPolicySchema, runnerRepositoryContextSchema, runnerRunIdentitySchema, runnerTaskSchema } from "./runner-command-contract.js";
|
|
1
2
|
import { normalizeRunnerRepositoryForSubmit } from "./git-remote-url.js";
|
|
2
3
|
import { compileScheduleArtifact, generateScheduleArtifact, parseScheduleArtifact } from "./planning/generate.js";
|
|
3
|
-
import { buildRunnerCommandPayload, runnerDeliverySchema, runnerHookPolicySchema, runnerRepositoryContextSchema, runnerRunIdentitySchema, runnerTaskSchema } from "./runner-command-contract.js";
|
|
4
4
|
import { workflowSubmitResultSchema } from "./workflow-submit-contract.js";
|
|
5
5
|
import { buildCommandScheduleYaml, submitRunnerArgoWorkflow } from "./argo-submit.js";
|
|
6
6
|
import { z } from "zod";
|
|
7
7
|
import { readFileSync } from "node:fs";
|
|
8
|
-
import { randomBytes } from "node:crypto";
|
|
9
|
-
import parseGitUrl from "git-url-parse";
|
|
10
8
|
import { resolve } from "node:path";
|
|
9
|
+
import { randomBytes } from "node:crypto";
|
|
11
10
|
import { simpleGit } from "simple-git";
|
|
11
|
+
import parseGitUrl from "git-url-parse";
|
|
12
12
|
//#region src/moka-submit.ts
|
|
13
13
|
const imagePullPolicySchema = z.enum([
|
|
14
14
|
"Always",
|
package/dist/pipeline-runtime.js
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
import { loadPipelineConfig } from "./config/load.js";
|
|
2
2
|
import "./config.js";
|
|
3
|
+
import { findPlannedNode } from "./planned-node.js";
|
|
3
4
|
import { parseJsonObject } from "./runtime/json-validation/json-validation.js";
|
|
4
5
|
import "./runtime/json-validation/index.js";
|
|
5
6
|
import { emitNodeFinish, emitNodeOutputRecorded, emitNodeStart, emitWorkflowFinish, emitWorkflowPlanned, emitWorkflowStarted, runtimeNodeActorDescriptor } from "./runtime/events/events.js";
|
|
6
7
|
import "./runtime/events/index.js";
|
|
7
|
-
import { executeCommand } from "./runtime/command-executor/command-executor.js";
|
|
8
|
-
import "./runtime/command-executor/index.js";
|
|
9
|
-
import { dispatchHooks } from "./runtime/hooks/hooks.js";
|
|
10
|
-
import "./runtime/hooks/index.js";
|
|
11
|
-
import { findPlannedNode } from "./planned-node.js";
|
|
12
8
|
import { executeAgentNode } from "./runtime/agent-node/agent-node.js";
|
|
13
9
|
import "./runtime/agent-node/index.js";
|
|
14
10
|
import { createRuntimeContext } from "./runtime/context/context.js";
|
|
15
11
|
import "./runtime/context/index.js";
|
|
12
|
+
import { executeCommand } from "./runtime/command-executor/command-executor.js";
|
|
13
|
+
import "./runtime/command-executor/index.js";
|
|
16
14
|
import { executeBuiltin } from "./runtime/builtins/builtins.js";
|
|
17
15
|
import "./runtime/builtins/index.js";
|
|
18
16
|
import { diffChangedFiles, snapshotChangedFiles } from "./runtime/changed-files/changed-files.js";
|
|
19
17
|
import "./runtime/changed-files/index.js";
|
|
20
18
|
import { evaluateNodeGates } from "./runtime/gates/gates.js";
|
|
21
19
|
import "./runtime/gates/index.js";
|
|
20
|
+
import { dispatchHooks } from "./runtime/hooks/hooks.js";
|
|
21
|
+
import "./runtime/hooks/index.js";
|
|
22
22
|
import { LocalScheduler } from "./runtime/local-scheduler.js";
|
|
23
23
|
import { NodeStateTracker } from "./runtime/node-state-tracker.js";
|
|
24
24
|
import { configUsesOpencode, leaseOpencodeRuntime } from "./runtime/opencode-runtime.js";
|
|
@@ -73,6 +73,7 @@ function runWithLeasedOpencode(options, config, worktreePath, run) {
|
|
|
73
73
|
return Effect.scoped(Effect.gen(function* () {
|
|
74
74
|
const lease = yield* Effect.acquireRelease(Effect.tryPromise(() => leaseOpencodeRuntime({
|
|
75
75
|
config,
|
|
76
|
+
...options.reporter ? { onSession: opencodeSessionReporter(options.reporter) } : {},
|
|
76
77
|
...options.signal ? { signal: options.signal } : {},
|
|
77
78
|
worktreePath
|
|
78
79
|
})), (lease) => Effect.promise(() => lease.release()));
|
|
@@ -83,6 +84,15 @@ function runWithLeasedOpencode(options, config, worktreePath, run) {
|
|
|
83
84
|
});
|
|
84
85
|
}));
|
|
85
86
|
}
|
|
87
|
+
function opencodeSessionReporter(reporter) {
|
|
88
|
+
return (nodeId, sessionId) => {
|
|
89
|
+
reporter({
|
|
90
|
+
nodeId,
|
|
91
|
+
sessionId,
|
|
92
|
+
type: "node.session"
|
|
93
|
+
});
|
|
94
|
+
};
|
|
95
|
+
}
|
|
86
96
|
function runJournalPath(context, dir) {
|
|
87
97
|
return join(context.worktreePath ?? process.cwd(), dir, `${context.runId}.jsonl`);
|
|
88
98
|
}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { workflowSchema } from "../config/schemas.js";
|
|
2
2
|
import { validatePipelineConfig } from "../config/validate.js";
|
|
3
3
|
import "../config.js";
|
|
4
|
+
import { dependentsByNeed, flattenNodes, hasReachableDependent } from "./graph.js";
|
|
4
5
|
import { createRunnerLaunchPlan, runLaunchPlan } from "../runner.js";
|
|
5
6
|
import { normalizeRunnerOutput } from "../runner-output.js";
|
|
7
|
+
import { compileWorkflowPlan } from "./compile.js";
|
|
6
8
|
import { loadBacklogPlanningContext } from "../schedule/backlog-context.js";
|
|
7
9
|
import { baselineScheduleArtifact } from "../schedule/baseline.js";
|
|
8
|
-
import { dependentsByNeed, flattenNodes, hasReachableDependent } from "./graph.js";
|
|
9
10
|
import { isCoverageNode, isImplementationNode } from "../schedule/scheduling-roles.js";
|
|
10
11
|
import { addGeneratedImplementationCoverage } from "../schedule/passes/coverage.js";
|
|
11
12
|
import { canonicalizeGeneratedScheduleIds } from "../schedule/passes/ids.js";
|
|
@@ -13,7 +14,6 @@ import { SCHEDULE_PASS_ORDER } from "../schedule/passes/index.js";
|
|
|
13
14
|
import { applyNodeCatalogModelFallbacks } from "../schedule/passes/models.js";
|
|
14
15
|
import { namespaceScheduleWorkflows } from "../schedule/passes/references.js";
|
|
15
16
|
import { plannerPrompt, plannerRepairPrompt } from "../schedule/prompts.js";
|
|
16
|
-
import { compileWorkflowPlan } from "./compile.js";
|
|
17
17
|
import { parseDocument, stringify } from "yaml";
|
|
18
18
|
import { z } from "zod";
|
|
19
19
|
import { Data } from "effect";
|