@oisincoveney/pipeline 3.14.0 → 3.15.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.
@@ -1,10 +1,10 @@
1
1
  import { ArgoGraphCompilerError, compileArgoExecutionGraph } from "./argo-graph.js";
2
2
  import { brokerAuthOptionSchema } from "./broker-auth.js";
3
+ import { compileScheduleArtifact, parseScheduleArtifact } from "./planning/generate.js";
3
4
  import { parseRunnerCommandPayload, runnerCommandPayloadSchema } from "./runner-command-contract.js";
4
5
  import { buildRunnerTaskDescriptor } from "./runner-command/task-descriptor.js";
5
6
  import { buildRunnerArgoWorkflowManifest, runnerArgoWorkflowManifestSchema } from "./argo-workflow.js";
6
7
  import { normalizeRunnerRepositoryForSubmit } from "./git-remote-url.js";
7
- import { compileScheduleArtifact, parseScheduleArtifact } from "./planning/generate.js";
8
8
  import { KubernetesArgoService, KubernetesArgoServiceLive } from "./runtime/services/kubernetes-argo-service.js";
9
9
  import { workflowSubmitResultSchema } from "./workflow-submit-contract.js";
10
10
  import { stringify } from "yaml";
@@ -2,13 +2,14 @@ import { loadPipelineConfig } from "../config/load.js";
2
2
  import "../config.js";
3
3
  import { loadMokaGlobalConfig } from "../moka-global-config.js";
4
4
  import { flattenNodes } from "../planning/graph.js";
5
- import { configureGatewayHosts, localGatewayStatus, reconcileGateway, renderGatewayConfig, runGatewayDoctor, startLocalGateway } from "../mcp/gateway.js";
6
5
  import { createOrchestratorLaunchPlan, createRunnerLaunchPlan } from "../runner.js";
7
6
  import { compileWorkflowPlan } from "../planning/compile.js";
7
+ import { compileScheduleArtifact, generateScheduleArtifact, parseScheduleArtifact } from "../planning/generate.js";
8
+ import { withRunControlStoreScoped } from "../run-control/run-control-store.js";
9
+ import { configureGatewayHosts, localGatewayStatus, reconcileGateway, renderGatewayConfig, runGatewayDoctor, startLocalGateway } from "../mcp/gateway.js";
8
10
  import { generateRuntimeRunId, resolveWorkflowSelection } from "../runtime/context/context.js";
9
11
  import "../runtime/context/index.js";
10
12
  import { runPipelineFromConfig } from "../pipeline-runtime.js";
11
- import { compileScheduleArtifact, generateScheduleArtifact, parseScheduleArtifact } from "../planning/generate.js";
12
13
  import { formatCodexAuthSyncResult, syncLocalCodexAuth } from "../codex-auth-sync.js";
13
14
  import { registerBenchCommand } from "../commands/bench-command.js";
14
15
  import { registerConfiguredEntrypointCommands } from "../commands/pipeline-command.js";
@@ -19,7 +20,6 @@ import { formatConfigLintWarning, lintPipelineConfig } from "../config/lint.js";
19
20
  import { parseLoopFlags, runLoopSubmit } from "../loop/loop-command.js";
20
21
  import { runLoopControllerEntrypoint } from "../loop/loop-controller-entrypoint.js";
21
22
  import { formatPipelineInitResult, initPipelineProject } from "../pipeline-init.js";
22
- import { withRunControlStoreScoped } from "../run-control/run-control-store.js";
23
23
  import { registerRunControlCommands } from "../run-control/commands.js";
24
24
  import { startDetachedRunController } from "../run-control/detach.js";
25
25
  import { createRunStoreRuntimeReporter } from "../run-control/runtime-reporter.js";
@@ -78,10 +78,12 @@ async function runConfiguredPipeline(rawInputs) {
78
78
  const inputs = withRunId(rawInputs);
79
79
  const config = loadPipelineConfig(inputs.worktreePath, { allowMissingLintFileReferences: true });
80
80
  if (inputs.schedule) {
81
- const compiled = compileScheduleArtifact(config, parseScheduleArtifact(readFileSync(inputs.schedule, "utf8"), inputs.schedule), inputs.worktreePath);
81
+ const scheduleYaml = readFileSync(inputs.schedule, "utf8");
82
+ const compiled = compileScheduleArtifact(config, parseScheduleArtifact(scheduleYaml, inputs.schedule), inputs.worktreePath);
82
83
  await runAndPrintPipeline({
83
84
  ...inputs,
84
85
  config: compiled.config,
86
+ scheduleArtifact: scheduleYaml,
85
87
  workflow: compiled.workflowId
86
88
  });
87
89
  return;
@@ -103,10 +105,12 @@ async function runConfiguredPipeline(rawInputs) {
103
105
  worktreePath: inputs.worktreePath
104
106
  });
105
107
  console.log(`Schedule generated: ${result.path}`);
106
- const compiled = compileScheduleArtifact(config, parseScheduleArtifact(readFileSync(resolve(inputs.worktreePath, result.path), "utf8"), result.path), inputs.worktreePath);
108
+ const scheduleYaml = readFileSync(resolve(inputs.worktreePath, result.path), "utf8");
109
+ const compiled = compileScheduleArtifact(config, parseScheduleArtifact(scheduleYaml, result.path), inputs.worktreePath);
107
110
  await runAndPrintPipeline({
108
111
  ...inputs,
109
112
  config: compiled.config,
113
+ scheduleArtifact: scheduleYaml,
110
114
  workflow: compiled.workflowId
111
115
  });
112
116
  return;
@@ -155,7 +159,8 @@ async function createLocalRunStoreRuntimeReporter(inputs, reporter, store) {
155
159
  await Effect.runPromise(store.createRun({
156
160
  ...resolvedRunControlOptions(inputs.runControl),
157
161
  nodeIds: plannedRunStoreNodeIds(inputs),
158
- runId
162
+ runId,
163
+ ...inputs.scheduleArtifact ? { schedule: inputs.scheduleArtifact } : {}
159
164
  }));
160
165
  return createRunStoreRuntimeReporter({
161
166
  reporter,
@@ -457,7 +462,8 @@ async function runDetachedResolvedTask(task, execution, runControl) {
457
462
  workflow: prepared.workflow,
458
463
  worktreePath
459
464
  }),
460
- runId
465
+ runId,
466
+ ...prepared.scheduleArtifact ? { schedule: prepared.scheduleArtifact } : {}
461
467
  });
462
468
  const launch = yield* Effect.tryPromise({
463
469
  catch: (error) => error,
@@ -486,10 +492,12 @@ async function runDetachedResolvedTask(task, execution, runControl) {
486
492
  async function prepareDetachedRun(input) {
487
493
  if (input.execution.schedule) {
488
494
  const schedule = resolve(input.execution.schedule);
489
- const compiled = compileScheduleArtifact(input.config, parseScheduleArtifact(readFileSync(schedule, "utf8"), schedule), input.worktreePath);
495
+ const scheduleYaml = readFileSync(schedule, "utf8");
496
+ const compiled = compileScheduleArtifact(input.config, parseScheduleArtifact(scheduleYaml, schedule), input.worktreePath);
490
497
  return {
491
498
  config: compiled.config,
492
499
  schedule,
500
+ scheduleArtifact: scheduleYaml,
493
501
  workflow: compiled.workflowId
494
502
  };
495
503
  }
@@ -508,10 +516,12 @@ async function prepareDetachedRun(input) {
508
516
  });
509
517
  console.log(`Schedule generated: ${result.path}`);
510
518
  const schedule = resolve(input.worktreePath, result.path);
511
- const compiled = compileScheduleArtifact(input.config, parseScheduleArtifact(readFileSync(schedule, "utf8"), result.path), input.worktreePath);
519
+ const scheduleYaml = readFileSync(schedule, "utf8");
520
+ const compiled = compileScheduleArtifact(input.config, parseScheduleArtifact(scheduleYaml, result.path), input.worktreePath);
512
521
  return {
513
522
  config: compiled.config,
514
523
  schedule,
524
+ scheduleArtifact: scheduleYaml,
515
525
  workflow: compiled.workflowId
516
526
  };
517
527
  }
@@ -1,10 +1,10 @@
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 { RepoIoService, runRepoIoSync } from "../runtime/services/repo-io-service.js";
5
- import { renderOpenCodeGatewayConfig } from "../mcp/gateway.js";
6
4
  import { protectedPermissionOverlay } from "../runtime/protected-paths/protected-paths.js";
5
+ import { RepoIoService, runRepoIoSync } from "../runtime/services/repo-io-service.js";
7
6
  import { compileWorkflowPlan } from "../planning/compile.js";
7
+ import { renderOpenCodeGatewayConfig } from "../mcp/gateway.js";
8
8
  import { opencodeAgentName } from "../runtime/opencode-agent-name.js";
9
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";
10
10
  import { mergeOpenCodeProjectConfig } from "../opencode-project-config.js";
@@ -5,8 +5,8 @@ import { existsSync, readFileSync, statSync } from "node:fs";
5
5
  import { execa } from "execa";
6
6
  import { tmpdir } from "node:os";
7
7
  import { dirname, join, relative } from "node:path";
8
- import { createHash } from "node:crypto";
9
8
  import { mkdir, mkdtemp, readdir, rm, writeFile } from "node:fs/promises";
9
+ import { createHash } from "node:crypto";
10
10
  //#region src/install-hooks.ts
11
11
  const DEFAULT_HOOK_INSTALL_SOURCE = AGENT_ASSET_SOURCE;
12
12
  const HOOK_HOSTS = [
@@ -6,13 +6,13 @@ import { z } from "zod";
6
6
  //#region src/moka-submit.d.ts
7
7
  declare const mokaSubmitDirectHooksSchema: z.ZodRecord<z.ZodEnum<{
8
8
  "workflow.start": "workflow.start";
9
- "node.finish": "node.finish";
10
- "node.start": "node.start";
11
9
  "workflow.success": "workflow.success";
12
10
  "workflow.failure": "workflow.failure";
13
11
  "workflow.complete": "workflow.complete";
12
+ "node.start": "node.start";
14
13
  "node.success": "node.success";
15
14
  "node.error": "node.error";
15
+ "node.finish": "node.finish";
16
16
  "gate.failure": "gate.failure";
17
17
  }> & z.core.$partial, z.ZodDiscriminatedUnion<[z.ZodObject<{
18
18
  failure: z.ZodDefault<z.ZodEnum<{
@@ -99,13 +99,13 @@ declare const mokaSubmitOptionsSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
99
99
  }, z.core.$strict>>;
100
100
  hooks: z.ZodOptional<z.ZodRecord<z.ZodEnum<{
101
101
  "workflow.start": "workflow.start";
102
- "node.finish": "node.finish";
103
- "node.start": "node.start";
104
102
  "workflow.success": "workflow.success";
105
103
  "workflow.failure": "workflow.failure";
106
104
  "workflow.complete": "workflow.complete";
105
+ "node.start": "node.start";
107
106
  "node.success": "node.success";
108
107
  "node.error": "node.error";
108
+ "node.finish": "node.finish";
109
109
  "gate.failure": "gate.failure";
110
110
  }> & z.core.$partial, z.ZodDiscriminatedUnion<[z.ZodObject<{
111
111
  failure: z.ZodDefault<z.ZodEnum<{
@@ -220,13 +220,13 @@ declare const mokaSubmitOptionsSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
220
220
  }, z.core.$strict>>;
221
221
  hooks: z.ZodOptional<z.ZodRecord<z.ZodEnum<{
222
222
  "workflow.start": "workflow.start";
223
- "node.finish": "node.finish";
224
- "node.start": "node.start";
225
223
  "workflow.success": "workflow.success";
226
224
  "workflow.failure": "workflow.failure";
227
225
  "workflow.complete": "workflow.complete";
226
+ "node.start": "node.start";
228
227
  "node.success": "node.success";
229
228
  "node.error": "node.error";
229
+ "node.finish": "node.finish";
230
230
  "gate.failure": "gate.failure";
231
231
  }> & z.core.$partial, z.ZodDiscriminatedUnion<[z.ZodObject<{
232
232
  failure: z.ZodDefault<z.ZodEnum<{
@@ -1,7 +1,7 @@
1
1
  import { brokerAuthOptionSchema } from "./broker-auth.js";
2
+ import { compileScheduleArtifact, generateScheduleArtifact, parseScheduleArtifact } from "./planning/generate.js";
2
3
  import { buildRunnerCommandPayload, runnerDeliverySchema, runnerHookPolicySchema, runnerRepositoryContextSchema, runnerRunIdentitySchema, runnerTaskSchema } from "./runner-command-contract.js";
3
4
  import { normalizeRunnerRepositoryForSubmit } from "./git-remote-url.js";
4
- import { compileScheduleArtifact, generateScheduleArtifact, parseScheduleArtifact } from "./planning/generate.js";
5
5
  import { workflowSubmitResultSchema } from "./workflow-submit-contract.js";
6
6
  import { buildCommandScheduleYaml, submitRunnerArgoWorkflow } from "./argo-submit.js";
7
7
  import { z } from "zod";
@@ -2,6 +2,8 @@ import { loadPipelineConfig } from "./config/load.js";
2
2
  import "./config.js";
3
3
  import { loadMokaDbUrl } from "./moka-global-config.js";
4
4
  import { findPlannedNode } from "./planned-node.js";
5
+ import { compileScheduleArtifact, parseScheduleArtifact } from "./planning/generate.js";
6
+ import { resolveRunControlStore } from "./run-control/run-control-store.js";
5
7
  import { parseJsonObject } from "./runtime/json-validation/json-validation.js";
6
8
  import "./runtime/json-validation/index.js";
7
9
  import { emitNodeFinish, emitNodeOutputRecorded, emitNodeStart, emitWorkflowFinish, emitWorkflowPlanned, emitWorkflowStarted, runtimeNodeActorDescriptor } from "./runtime/events/events.js";
@@ -35,7 +37,22 @@ function runPipelineFromConfig(options) {
35
37
  }
36
38
  function resumeRun(options) {
37
39
  const { dbUrl, ...runtimeOptions } = options;
38
- return Effect.runPromise(withOpencodeRuntime(runtimeOptions, (resolved) => resumeRunWithContext(createRuntimeContext(resolved), dbUrl)));
40
+ return Effect.runPromise(Effect.scoped(resolveResumeRuntimeOptions(runtimeOptions, dbUrl).pipe(Effect.flatMap((resolved) => withOpencodeRuntime(resolved, (inner) => resumeRunWithContext(createRuntimeContext(inner), dbUrl))))));
41
+ }
42
+ function resolveResumeRuntimeOptions(options, dbUrl) {
43
+ if (dbUrl === void 0) return Effect.succeed(options);
44
+ const worktreePath = options.worktreePath ?? process.cwd();
45
+ return resolveRunControlStore(dbUrl, worktreePath).pipe(Effect.flatMap((store) => store.readRun({ runId: options.runId })), Effect.map((manifest) => applyPersistedSchedule(options, manifest, worktreePath)));
46
+ }
47
+ function applyPersistedSchedule(options, manifest, worktreePath) {
48
+ const schedule = manifest?.schedule;
49
+ if (!schedule) return options;
50
+ const compiled = compileScheduleArtifact(options.config ?? loadPipelineConfig(worktreePath), parseScheduleArtifact(schedule, "persisted schedule"), worktreePath);
51
+ return {
52
+ ...options,
53
+ config: compiled.config,
54
+ workflowId: compiled.workflowId
55
+ };
39
56
  }
40
57
  function runScheduledWorkflowTask(options) {
41
58
  const { dependencyOutputs, nodeId, ...runtimeOptions } = options;
@@ -2,10 +2,9 @@ import { workflowSchema } from "../config/schemas.js";
2
2
  import { validatePipelineConfig } from "../config/validate.js";
3
3
  import "../config.js";
4
4
  import { dependentsByNeed, flattenNodes, hasReachableDependent } from "./graph.js";
5
+ import { ensurePipelineWorkspaceIgnore } from "../run-control/workspace.js";
5
6
  import { createRunnerLaunchPlan, runLaunchPlan } from "../runner.js";
6
7
  import { normalizeRunnerOutput } from "../runner-output.js";
7
- import { compileWorkflowPlan } from "./compile.js";
8
- import { ensurePipelineWorkspaceIgnore } from "../run-control/workspace.js";
9
8
  import { loadBacklogPlanningContext } from "../schedule/backlog-context.js";
10
9
  import { baselineScheduleArtifact } from "../schedule/baseline.js";
11
10
  import { isCoverageNode, isImplementationNode, isWriteCapableParallelChild } from "../schedule/scheduling-roles.js";
@@ -17,6 +16,7 @@ import { applyNodeCatalogModelFallbacks } from "../schedule/passes/models.js";
17
16
  import { appendPullRequestDelivery } from "../schedule/passes/open-pull-request.js";
18
17
  import { namespaceScheduleWorkflows } from "../schedule/passes/references.js";
19
18
  import { plannerPrompt, plannerRepairPrompt } from "../schedule/prompts.js";
19
+ import { compileWorkflowPlan } from "./compile.js";
20
20
  import { parseDocument, stringify } from "yaml";
21
21
  import { z } from "zod";
22
22
  import { Data } from "effect";
@@ -1,7 +1,7 @@
1
1
  import { loadMokaDbUrl } from "../moka-global-config.js";
2
+ import { withRunControlStoreScoped } from "./run-control-store.js";
2
3
  import { resumeRun } from "../pipeline-runtime.js";
3
4
  import { registerNextNodeSubcommand } from "./next-node.js";
4
- import { withRunControlStoreScoped } from "./run-control-store.js";
5
5
  import { registerSubmitResultSubcommand } from "./submit-result.js";
6
6
  import { Effect } from "effect";
7
7
  import { join, relative, sep } from "node:path";
@@ -94,6 +94,7 @@ const mokaRunManifestSchema = z.object({
94
94
  mode: runModeSchema,
95
95
  nodes: z.record(nonEmptyStringSchema, mokaNodeStatusSchema),
96
96
  runId: nonEmptyStringSchema,
97
+ schedule: nonEmptyStringSchema.optional(),
97
98
  staleDetection: runControlStaleDetectionSchema.optional(),
98
99
  status: mokaRunStatusSchema,
99
100
  target: runTargetSchema
@@ -1,8 +1,8 @@
1
1
  import { Effect } from "effect";
2
2
  import { existsSync } from "node:fs";
3
3
  import { dirname, join } from "node:path";
4
- import { spawn } from "node:child_process";
5
4
  import { fileURLToPath } from "node:url";
5
+ import { spawn } from "node:child_process";
6
6
  //#region src/run-control/detach.ts
7
7
  function startDetachedRunController(input) {
8
8
  return Effect.runPromise(startDetachedRunControllerEffect(input));
@@ -1,7 +1,8 @@
1
1
  import { loadPipelineConfig } from "../config/load.js";
2
- import { loadMokaGlobalConfig } from "../moka-global-config.js";
3
- import { computeReadyNodeIds } from "../runtime/scheduler.js";
2
+ import { loadMokaDbUrl } from "../moka-global-config.js";
4
3
  import { compileScheduleArtifact, parseScheduleArtifact } from "../planning/generate.js";
4
+ import { postgresDurableRunStore } from "../runtime/durable-store/postgres/postgres-store.js";
5
+ import { computeReadyNodeIds } from "../runtime/scheduler.js";
5
6
  import { inMemoryDurableRunStore } from "../runtime/durable-store/durable-store.js";
6
7
  import { Effect } from "effect";
7
8
  import { readFile } from "node:fs/promises";
@@ -50,18 +51,22 @@ function buildNextNodeEnvelope(input) {
50
51
  };
51
52
  }
52
53
  /**
53
- * PIPE-91.6: resolve the {@link DurableRunStore} for this invocation using the
54
- * same `db.url`-presence selection as `pipeline-runtime.ts`. Both branches
55
- * return `inMemoryDurableRunStore()` until PIPE-91.4 delivers the Postgres impl;
56
- * the selection is wired so 91.4 can substitute `postgresStore(dbUrl)` here
57
- * without touching any other call site.
54
+ * PIPE-91.15: resolve the {@link DurableRunStore} for this invocation as a
55
+ * scoped resource, mirroring `pipeline-runtime.ts`'s `acquireRunJournal`
56
+ * lifecycle. When `db.url` is set, acquire the Postgres-backed store
57
+ * ({@link postgresDurableRunStore}, scoped to `runId`) and release it flushing
58
+ * pending write-through persistence then closing the connection pool — when the
59
+ * scope exits. When `db.url` is absent, yield the zero-infra in-memory store
60
+ * (nothing to release). Returning a scoped Effect is what guarantees
61
+ * `submit-result` awaits its write and closes the client before the process
62
+ * exits; without that flush the record is lost (the PIPE-91.15 dogfood failure).
58
63
  *
59
- * Exported so PIPE-91.7 (`submit-result`) reuses the same seam without
60
- * duplicating the selection logic.
64
+ * Exported so `submit-result` (PIPE-91.7) reuses the same selection + lifecycle
65
+ * seam without duplicating it.
61
66
  */
62
- function resolveDurableStore(dbUrl) {
63
- if (dbUrl !== void 0) return inMemoryDurableRunStore();
64
- return inMemoryDurableRunStore();
67
+ function resolveDurableStore(dbUrl, runId) {
68
+ if (dbUrl === void 0) return Effect.succeed(inMemoryDurableRunStore());
69
+ return Effect.acquireRelease(Effect.tryPromise(() => postgresDurableRunStore(dbUrl, runId)), (store) => Effect.promise(() => store.close()));
65
70
  }
66
71
  /**
67
72
  * PIPE-91.6: register `moka next node <run-id> --schedule-file <path>` under
@@ -74,6 +79,9 @@ function registerNextNodeSubcommand(nextCommand) {
74
79
  });
75
80
  }
76
81
  function printNextNodeEnvelopeEffect(runId, scheduleFile) {
82
+ return Effect.scoped(printNextNodeEnvelopeScoped(runId, scheduleFile));
83
+ }
84
+ function printNextNodeEnvelopeScoped(runId, scheduleFile) {
77
85
  return Effect.gen(function* () {
78
86
  const scheduleRaw = yield* Effect.tryPromise({
79
87
  catch: (error) => error,
@@ -89,16 +97,14 @@ function printNextNodeEnvelopeEffect(runId, scheduleFile) {
89
97
  try: () => compileScheduleArtifact(config, parseScheduleArtifact(scheduleRaw, scheduleFile), cwd)
90
98
  });
91
99
  const nodes = plan.topologicalOrder;
92
- const nodeMetadata = new Map(plan.topologicalOrder.map((node) => [node.id, {
93
- criteria: node.taskContext?.acceptanceCriteria ?? [],
94
- prompt: node.taskContext?.description ?? node.id
95
- }]));
96
- const dbUrl = loadMokaGlobalConfig()?.momokaya?.db?.url;
97
100
  const envelope = buildNextNodeEnvelope({
98
- nodeMetadata,
101
+ nodeMetadata: new Map(plan.topologicalOrder.map((node) => [node.id, {
102
+ criteria: node.taskContext?.acceptanceCriteria ?? [],
103
+ prompt: node.taskContext?.description ?? node.id
104
+ }])),
99
105
  nodes,
100
106
  runId,
101
- store: resolveDurableStore(dbUrl)
107
+ store: yield* resolveDurableStore(loadMokaDbUrl(), runId)
102
108
  });
103
109
  if (envelope === void 0) {
104
110
  process.stdout.write("No ready nodes — run is complete or all remaining nodes are blocked.\n");
@@ -177,6 +177,7 @@ function buildBaseManifest(input) {
177
177
  mode: parseRunMode(input.mode),
178
178
  nodes,
179
179
  runId: input.runId,
180
+ ...input.schedule ? { schedule: input.schedule } : {},
180
181
  staleDetection: parseRunControlStaleDetection(input.staleDetection ?? DEFAULT_RUN_CONTROL_STALE_DETECTION),
181
182
  status: "queued",
182
183
  target: parseRunTarget(input.target)
@@ -59,4 +59,4 @@ function withRunControlStoreScoped(workspaceRoot, use) {
59
59
  return Effect.scoped(resolveRunControlStore(loadMokaDbUrl(), workspaceRoot).pipe(Effect.flatMap(use)));
60
60
  }
61
61
  //#endregion
62
- export { fileRunControlStore, withRunControlStoreScoped };
62
+ export { fileRunControlStore, resolveRunControlStore, withRunControlStoreScoped };
@@ -1,5 +1,5 @@
1
- import { withRunStateLock } from "./run-state-lock.js";
2
1
  import { fileRunControlStore } from "./run-control-store.js";
2
+ import { withRunStateLock } from "./run-state-lock.js";
3
3
  import { Effect } from "effect";
4
4
  import { isAbsolute, join } from "node:path";
5
5
  import { appendFile, mkdir } from "node:fs/promises";
@@ -146,6 +146,7 @@ function createRunManifest(input) {
146
146
  mode: parseRunMode(input.mode),
147
147
  nodes,
148
148
  runId,
149
+ ...input.schedule ? { schedule: input.schedule } : {},
149
150
  staleDetection: parseRunControlStaleDetection(input.staleDetection ?? DEFAULT_RUN_CONTROL_STALE_DETECTION),
150
151
  status: "queued",
151
152
  target: parseRunTarget(input.target)
@@ -1,4 +1,4 @@
1
- import { loadMokaGlobalConfig } from "../moka-global-config.js";
1
+ import { loadMokaDbUrl } from "../moka-global-config.js";
2
2
  import { resolveDurableStore } from "./next-node.js";
3
3
  import { parseSubmitResult } from "../runtime/node-protocol/node-protocol.js";
4
4
  import { Effect } from "effect";
@@ -41,19 +41,19 @@ function registerSubmitResultSubcommand(program) {
41
41
  });
42
42
  }
43
43
  function submitResultEffect(runId, nodeId, resultJson) {
44
- return Effect.try({
45
- catch: (error) => error,
46
- try: () => {
47
- const dbUrl = loadMokaGlobalConfig()?.momokaya?.db?.url;
48
- recordSubmitResult({
44
+ return Effect.scoped(Effect.gen(function* () {
45
+ const store = yield* resolveDurableStore(loadMokaDbUrl(), runId);
46
+ yield* Effect.try({
47
+ catch: (error) => error,
48
+ try: () => recordSubmitResult({
49
49
  nodeId,
50
50
  resultJson,
51
51
  runId,
52
- store: resolveDurableStore(dbUrl)
53
- });
54
- process.stdout.write(`Recorded result for run ${runId} node ${nodeId}.\n`);
55
- }
56
- });
52
+ store
53
+ })
54
+ });
55
+ process.stdout.write(`Recorded result for run ${runId} node ${nodeId}.\n`);
56
+ }));
57
57
  }
58
58
  //#endregion
59
59
  export { registerSubmitResultSubcommand };
@@ -1,10 +1,10 @@
1
1
  import { PIPELINE_CONFIG_PATH, PROFILES_CONFIG_PATH, RUNNERS_CONFIG_PATH } from "../config/defaults.js";
2
2
  import { loadPipelineConfig, parsePipelineConfigParts } from "../config/load.js";
3
3
  import "../config.js";
4
+ import { compileScheduleArtifact, parseScheduleArtifact } from "../planning/generate.js";
4
5
  import { initialNodeStateStore } from "../runtime/node-state-store.js";
5
6
  import { parseRunnerCommandPayload } from "../runner-command-contract.js";
6
7
  import { RunnerCommandIoService, createRunnerCommandEventSink } from "../runtime/services/runner-command-io-service.js";
7
- import { compileScheduleArtifact, parseScheduleArtifact } from "../planning/generate.js";
8
8
  import { runnerTaskTextEffect } from "./run.js";
9
9
  import { Effect } from "effect";
10
10
  import { join } from "node:path";
@@ -2,11 +2,11 @@ import { indexPlannedNodesById, resolveExecutableDependencyIds } from "../planni
2
2
  import { loadPipelineConfig } from "../config/load.js";
3
3
  import "../config.js";
4
4
  import { findPlannedNode } from "../planned-node.js";
5
+ import { compileScheduleArtifact, parseScheduleArtifact } from "../planning/generate.js";
5
6
  import { RunnerCommandPayloadValidationError, parseRunnerCommandPayload, resolveRunnerEventSinkAuthToken } from "../runner-command-contract.js";
6
7
  import { createRunnerEventSink } from "../runner-event-sink.js";
7
8
  import { RunnerCommandIoService, RunnerCommandIoServiceLive } from "../runtime/services/runner-command-io-service.js";
8
9
  import { readRunnerTaskDescriptorEffect } from "./task-descriptor.js";
9
- import { compileScheduleArtifact, parseScheduleArtifact } from "../planning/generate.js";
10
10
  import { z } from "zod";
11
11
  import { Effect } from "effect";
12
12
  import { resolve } from "node:path";
@@ -11,8 +11,8 @@ declare const runnerEventRecordSchema: z.ZodUnion<readonly [z.ZodObject<{
11
11
  runId: z.ZodString;
12
12
  sequence: z.ZodNumber;
13
13
  type: z.ZodEnum<{
14
- "workflow.planned": "workflow.planned";
15
14
  "workflow.start": "workflow.start";
15
+ "workflow.planned": "workflow.planned";
16
16
  }>;
17
17
  workflowPlan: z.ZodObject<{
18
18
  edges: z.ZodOptional<z.ZodArray<z.ZodObject<{
@@ -58,10 +58,10 @@ declare const runnerEventRecordSchema: z.ZodUnion<readonly [z.ZodObject<{
58
58
  }>;
59
59
  }, z.core.$strip>;
60
60
  type: z.ZodEnum<{
61
+ "node.start": "node.start";
62
+ "node.finish": "node.finish";
61
63
  "agent.finish": "agent.finish";
62
64
  "agent.start": "agent.start";
63
- "node.finish": "node.finish";
64
- "node.start": "node.start";
65
65
  }>;
66
66
  }, z.core.$strip>, z.ZodObject<{
67
67
  at: z.ZodOptional<z.ZodString>;
@@ -256,8 +256,8 @@ declare const runnerEventBatchSchema: z.ZodObject<{
256
256
  runId: z.ZodString;
257
257
  sequence: z.ZodNumber;
258
258
  type: z.ZodEnum<{
259
- "workflow.planned": "workflow.planned";
260
259
  "workflow.start": "workflow.start";
260
+ "workflow.planned": "workflow.planned";
261
261
  }>;
262
262
  workflowPlan: z.ZodObject<{
263
263
  edges: z.ZodOptional<z.ZodArray<z.ZodObject<{
@@ -303,10 +303,10 @@ declare const runnerEventBatchSchema: z.ZodObject<{
303
303
  }>;
304
304
  }, z.core.$strip>;
305
305
  type: z.ZodEnum<{
306
+ "node.start": "node.start";
307
+ "node.finish": "node.finish";
306
308
  "agent.finish": "agent.finish";
307
309
  "agent.start": "agent.start";
308
- "node.finish": "node.finish";
309
- "node.start": "node.start";
310
310
  }>;
311
311
  }, z.core.$strip>, z.ZodObject<{
312
312
  at: z.ZodOptional<z.ZodString>;
@@ -1,9 +1,9 @@
1
1
  import { resolvePackageAssetPath } from "../../package-assets.js";
2
2
  import { resolveFileReference } from "../../path-refs.js";
3
- import { gatewayServerForProfile } from "../../mcp/gateway.js";
4
- import { selectNodeModelCandidates } from "../../model-resolver.js";
5
3
  import { createRunnerLaunchPlan } from "../../runner.js";
6
4
  import { normalizeRunnerOutput, runnerTextCandidates } from "../../runner-output.js";
5
+ import { gatewayServerForProfile } from "../../mcp/gateway.js";
6
+ import { selectNodeModelCandidates } from "../../model-resolver.js";
7
7
  import { estimateTokens } from "../../token-estimator.js";
8
8
  import { normalizeJsonSource, readJsonSchemaSource, validateJsonSchemaSource } from "../json-validation/json-validation.js";
9
9
  import "../json-validation/index.js";
@@ -1,9 +1,9 @@
1
1
  import { loadPipelineConfig } from "../../config/load.js";
2
2
  import "../../config.js";
3
3
  import { runLaunchPlan } from "../../runner.js";
4
+ import { compileWorkflowPlan } from "../../planning/compile.js";
4
5
  import { createPublicRuntimeObservabilityEmitter } from "../events/events.js";
5
6
  import "../events/index.js";
6
- import { compileWorkflowPlan } from "../../planning/compile.js";
7
7
  import { initialNodeStateStore } from "../node-state-store.js";
8
8
  import { randomUUID } from "node:crypto";
9
9
  //#region src/runtime/context/context.ts
@@ -3,8 +3,8 @@ import { fileURLToPath } from "node:url";
3
3
  import { eq } from "drizzle-orm";
4
4
  import { drizzle } from "drizzle-orm/postgres-js";
5
5
  import "drizzle-orm/postgres-js/migrator";
6
- import pino from "pino";
7
6
  import postgres from "postgres";
7
+ import pino from "pino";
8
8
  //#region src/runtime/durable-store/postgres/postgres-store.ts
9
9
  const logger = pino({ name: "postgres-durable-store" });
10
10
  fileURLToPath(new URL("./migrations", import.meta.url));
package/package.json CHANGED
@@ -131,7 +131,7 @@
131
131
  "prepack": "bun run build:cli"
132
132
  },
133
133
  "type": "module",
134
- "version": "3.14.0",
134
+ "version": "3.15.0",
135
135
  "description": "Config-driven multi-agent pipeline runner for repository work",
136
136
  "main": "./dist/index.js",
137
137
  "types": "./dist/index.d.ts",