@oisincoveney/pipeline 3.15.6 → 3.16.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.
Files changed (56) hide show
  1. package/dist/argo-submit.d.ts +9 -5
  2. package/dist/argo-submit.js +5 -2
  3. package/dist/cli/program.js +1 -1
  4. package/dist/cli/run-commands.js +1 -1
  5. package/dist/cli/run-service.js +22 -21
  6. package/dist/cli/submit-options.js +1 -1
  7. package/dist/config/schemas.d.ts +4 -4
  8. package/dist/install-hooks.js +1 -1
  9. package/dist/install-rules.js +119 -40
  10. package/dist/moka-global-config.d.ts +11 -6
  11. package/dist/moka-global-config.js +25 -6
  12. package/dist/moka-submit.d.ts +20 -0
  13. package/dist/moka-submit.js +2 -0
  14. package/dist/pipeline-init.js +10 -6
  15. package/dist/pipeline-runtime.d.ts +40 -1
  16. package/dist/pipeline-runtime.js +60 -1
  17. package/dist/planning/generate.d.ts +6 -1
  18. package/dist/planning/generate.js +10 -3
  19. package/dist/remote/argo/model.d.ts +4 -0
  20. package/dist/remote/argo/model.js +12 -1
  21. package/dist/remote/argo/policy.js +8 -1
  22. package/dist/remote/submit/argo-submission.d.ts +4 -0
  23. package/dist/remote/submit/argo-submission.js +1 -0
  24. package/dist/remote/submit/compilation.d.ts +14 -3
  25. package/dist/remote/submit/compilation.js +3 -4
  26. package/dist/remote/submit/service.d.ts +12 -1
  27. package/dist/remote/submit/service.js +46 -6
  28. package/dist/run-control/contracts.d.ts +86 -1
  29. package/dist/run-control/logical-segment.js +2 -8
  30. package/dist/run-control/next-node.js +45 -49
  31. package/dist/run-control/postgres/postgres-run-control-store.js +4 -6
  32. package/dist/run-control/resume-command.js +42 -3
  33. package/dist/run-control/run-control-store.js +11 -35
  34. package/dist/run-control/run-record.js +35 -0
  35. package/dist/run-control/runtime-reporter.js +7 -4
  36. package/dist/run-control/store-fs-effects.js +3 -48
  37. package/dist/run-control/store-manifest.js +5 -72
  38. package/dist/run-control/store-paths.js +4 -28
  39. package/dist/run-control/store.js +9 -165
  40. package/dist/run-control/submit-result.js +6 -5
  41. package/dist/run-control/supervisor.js +1 -2
  42. package/dist/runner-command/lifecycle-context.js +7 -3
  43. package/dist/runner-command/lifecycle.js +56 -2
  44. package/dist/runner-command/run.js +165 -3
  45. package/dist/runtime/durable-store/acquisition.js +2 -3
  46. package/dist/runtime/durable-store/durable-store.d.ts +1 -0
  47. package/dist/runtime/durable-store/postgres/postgres-store.js +4 -14
  48. package/dist/runtime/journal-acquisition.js +1 -1
  49. package/dist/runtime/run-journal.js +23 -0
  50. package/dist/runtime/services/run-journal-file-service.js +20 -0
  51. package/dist/runtime/step/step-node.js +53 -0
  52. package/docs/moka-orchestrator-design.md +35 -4
  53. package/docs/operator-guide.md +50 -22
  54. package/docs/run-control.md +40 -0
  55. package/package.json +17 -5
  56. package/dist/runtime/durable-store/durable-store.js +0 -53
@@ -5,6 +5,15 @@ import { z } from "zod";
5
5
 
6
6
  //#region src/argo-submit.d.ts
7
7
  declare const submitRunnerArgoWorkflowOptionsSchema: z.ZodObject<{
8
+ brokerAuth: z.ZodObject<{
9
+ secretKey: z.ZodDefault<z.ZodString>;
10
+ secretName: z.ZodString;
11
+ url: z.ZodDefault<z.ZodString>;
12
+ }, z.core.$strict>;
13
+ dbAuth: z.ZodOptional<z.ZodObject<{
14
+ secretKey: z.ZodDefault<z.ZodString>;
15
+ secretName: z.ZodString;
16
+ }, z.core.$strict>>;
8
17
  eventAuthSecretKey: z.ZodOptional<z.ZodString>;
9
18
  eventAuthSecretName: z.ZodOptional<z.ZodString>;
10
19
  generateName: z.ZodOptional<z.ZodString>;
@@ -20,11 +29,6 @@ declare const submitRunnerArgoWorkflowOptionsSchema: z.ZodObject<{
20
29
  kubeconfigPath: z.ZodOptional<z.ZodString>;
21
30
  name: z.ZodOptional<z.ZodString>;
22
31
  namespace: z.ZodString;
23
- brokerAuth: z.ZodObject<{
24
- secretKey: z.ZodDefault<z.ZodString>;
25
- secretName: z.ZodString;
26
- url: z.ZodDefault<z.ZodString>;
27
- }, z.core.$strict>;
28
32
  payloadJson: z.ZodString;
29
33
  scheduleYaml: z.ZodString;
30
34
  serviceAccountName: z.ZodOptional<z.ZodString>;
@@ -1,4 +1,5 @@
1
1
  import { ArgoGraphCompilerError, compileArgoExecutionGraph } from "./argo-graph.js";
2
+ import { dbAuthOptionSchema } from "./remote/argo/model.js";
2
3
  import { brokerAuthOptionSchema } from "./credentials/broker.js";
3
4
  import { compileScheduleArtifact, parseScheduleArtifact } from "./planning/generate.js";
4
5
  import { parseRunnerCommandPayload, runnerCommandPayloadSchema } from "./runner-command-contract.js";
@@ -24,6 +25,8 @@ const configMapSchema = z.object({
24
25
  }).strict()
25
26
  }).strict();
26
27
  const submitRunnerArgoWorkflowOptionsSchema = z.object({
28
+ brokerAuth: brokerAuthOptionSchema,
29
+ dbAuth: dbAuthOptionSchema.optional(),
27
30
  eventAuthSecretKey: z.string().min(1).optional(),
28
31
  eventAuthSecretName: z.string().min(1).optional(),
29
32
  generateName: z.string().min(1).optional(),
@@ -39,7 +42,6 @@ const submitRunnerArgoWorkflowOptionsSchema = z.object({
39
42
  kubeconfigPath: z.string().min(1).optional(),
40
43
  name: z.string().min(1).optional(),
41
44
  namespace: z.string().min(1),
42
- brokerAuth: brokerAuthOptionSchema,
43
45
  payloadJson: z.string().min(1),
44
46
  scheduleYaml: z.string().min(1),
45
47
  serviceAccountName: z.string().min(1).optional()
@@ -78,6 +80,8 @@ function submitRunnerArgoWorkflowEffect(rawOptions, dependencies) {
78
80
  "pipeline.oisin.dev/ticket-project": payload.run.project,
79
81
  "pipeline.oisin.dev/ticket-title": payload.task.title
80
82
  } : {},
83
+ brokerAuth: options.brokerAuth,
84
+ dbAuth: options.dbAuth,
81
85
  eventAuthSecretKey: options.eventAuthSecretKey,
82
86
  eventAuthSecretName: options.eventAuthSecretName,
83
87
  generateName: options.generateName,
@@ -89,7 +93,6 @@ function submitRunnerArgoWorkflowEffect(rawOptions, dependencies) {
89
93
  labels,
90
94
  name: options.name,
91
95
  namespace: options.namespace,
92
- brokerAuth: options.brokerAuth,
93
96
  payloadConfigMapName,
94
97
  plan: compiled.plan,
95
98
  scheduleConfigMapName: scheduleArtifactConfigMapName,
@@ -4,13 +4,13 @@ import { registerBenchCommand } from "../commands/bench-command.js";
4
4
  import { registerConfiguredEntrypointCommands } from "../commands/pipeline-command.js";
5
5
  import { registerRunnerCommandCommand } from "../commands/runner-command-command.js";
6
6
  import { registerTicketCommand } from "../commands/ticket-command.js";
7
+ import { addMokaSubmitOptions, runMokaSubmitFromCli } from "./submit-options.js";
7
8
  import { registerRunControlCommands } from "../run-control/commands.js";
8
9
  import { registerBootstrapCommands } from "./bootstrap-commands.js";
9
10
  import { registerLoopCommand } from "./loop-commands.js";
10
11
  import { registerMcpGatewayCommands } from "./mcp-gateway-commands.js";
11
12
  import { registerPlanCommands } from "./plan-commands.js";
12
13
  import { execute } from "./run-service.js";
13
- import { addMokaSubmitOptions, runMokaSubmitFromCli } from "./submit-options.js";
14
14
  import { printMokaSubmitResult, registerRunCommands } from "./run-commands.js";
15
15
  import { Effect } from "effect";
16
16
  import { readFileSync } from "node:fs";
@@ -1,7 +1,7 @@
1
1
  import { MOKA_RUN_EFFORTS, MOKA_RUN_TARGETS, resolveMokaRun } from "./run-resolver.js";
2
+ import { runMokaSubmitFromCli } from "./submit-options.js";
2
3
  import { dispatchMokaRunCommand } from "./run-command.js";
3
4
  import { execute, runDetachedResolvedTask, runLocalResolvedTask } from "./run-service.js";
4
- import { runMokaSubmitFromCli } from "./submit-options.js";
5
5
  import { Option } from "commander";
6
6
  //#region src/cli/run-commands.ts
7
7
  function registerRunCommands(program, options = {}) {
@@ -1,15 +1,15 @@
1
1
  import { flattenNodes } from "../planning/graph.js";
2
2
  import { loadPipelineConfig } from "../config/load.js";
3
3
  import "../config.js";
4
+ import { withRunControlStoreScoped } from "../run-control/run-control-store.js";
4
5
  import { compileWorkflowPlan } from "../planning/compile.js";
5
6
  import { generateRuntimeRunId, resolveWorkflowSelection } from "../runtime/context/context.js";
6
7
  import "../runtime/context/index.js";
7
- import { compileScheduleArtifact, generateScheduleArtifact, parseScheduleArtifact } from "../planning/generate.js";
8
- import { withRunControlStoreScoped } from "../run-control/run-control-store.js";
8
+ import { compileScheduleArtifact, generateScheduleArtifactInMemory, parseScheduleArtifact } from "../planning/generate.js";
9
9
  import { runPipelineFromConfig } from "../pipeline-runtime.js";
10
+ import { createRunStoreRuntimeReporter } from "../run-control/runtime-reporter.js";
10
11
  import { createTerminalRuntimeReporter, formatRuntimeFailure, formatRuntimeResult } from "./format.js";
11
12
  import { startDetachedRunController } from "../run-control/detach.js";
12
- import { createRunStoreRuntimeReporter } from "../run-control/runtime-reporter.js";
13
13
  import { createRunControlSupervisor } from "../run-control/supervisor.js";
14
14
  import { Effect } from "effect";
15
15
  import { readFileSync } from "node:fs";
@@ -82,14 +82,7 @@ function persistDetachedRunController(input) {
82
82
  yield* store.createRun(detachedRunRecord(input));
83
83
  const launch = yield* Effect.tryPromise({
84
84
  catch: (error) => error,
85
- try: () => startDetachedRunController({
86
- entrypoint: input.prepared.entrypoint,
87
- runId: input.runId,
88
- schedule: input.prepared.schedule,
89
- task: input.task,
90
- workflow: input.prepared.workflow,
91
- workspaceRoot: input.worktreePath
92
- })
85
+ try: () => startDetachedRunController(detachedRunControllerInput(input))
93
86
  });
94
87
  yield* store.updateRunController({
95
88
  controller: {
@@ -103,6 +96,16 @@ function persistDetachedRunController(input) {
103
96
  });
104
97
  })));
105
98
  }
99
+ function detachedRunControllerInput(input) {
100
+ return {
101
+ entrypoint: input.prepared.entrypoint,
102
+ runId: input.runId,
103
+ ...input.prepared.schedule ? { schedule: input.prepared.schedule } : {},
104
+ task: input.task,
105
+ workflow: input.prepared.workflow,
106
+ workspaceRoot: input.worktreePath
107
+ };
108
+ }
106
109
  function detachedRunRecord(input) {
107
110
  return {
108
111
  ...resolvedRunControlOptions(input.runControl),
@@ -149,16 +152,16 @@ async function runConfiguredPipeline(rawInputs) {
149
152
  });
150
153
  return;
151
154
  }
152
- const result = await generateScheduleArtifact({
155
+ const result = await generateScheduleArtifactInMemory({
153
156
  config,
154
157
  entrypointId: scheduledEntrypoint,
155
158
  runId: inputs.runId,
156
159
  task: inputs.task,
157
160
  worktreePath: inputs.worktreePath
158
161
  });
159
- console.log(`Schedule generated: ${result.path}`);
160
- const scheduleYaml = readFileSync(resolve(inputs.worktreePath, result.path), "utf8");
161
- const compiled = compileScheduleArtifact(config, parseScheduleArtifact(scheduleYaml, result.path), inputs.worktreePath);
162
+ console.log("Schedule generated in memory");
163
+ const scheduleYaml = result.yaml;
164
+ const compiled = compileScheduleArtifact(config, parseScheduleArtifact(scheduleYaml, "schedule.yaml"), inputs.worktreePath);
162
165
  await runAndPrintPipeline({
163
166
  ...inputs,
164
167
  config: compiled.config,
@@ -327,20 +330,18 @@ async function prepareDetachedRun(input) {
327
330
  entrypoint: input.execution.entrypoint,
328
331
  workflow: input.execution.workflow
329
332
  };
330
- const result = await generateScheduleArtifact({
333
+ const result = await generateScheduleArtifactInMemory({
331
334
  config: input.config,
332
335
  entrypointId: scheduledEntrypoint,
333
336
  runId: input.runId,
334
337
  task: input.task,
335
338
  worktreePath: input.worktreePath
336
339
  });
337
- console.log(`Schedule generated: ${result.path}`);
338
- const schedule = resolve(input.worktreePath, result.path);
339
- const scheduleYaml = readFileSync(schedule, "utf8");
340
- const compiled = compileScheduleArtifact(input.config, parseScheduleArtifact(scheduleYaml, result.path), input.worktreePath);
340
+ console.log("Schedule generated in memory");
341
+ const scheduleYaml = result.yaml;
342
+ const compiled = compileScheduleArtifact(input.config, parseScheduleArtifact(scheduleYaml, "schedule.yaml"), input.worktreePath);
341
343
  return {
342
344
  config: compiled.config,
343
- schedule,
344
345
  scheduleArtifact: scheduleYaml,
345
346
  workflow: compiled.workflowId
346
347
  };
@@ -93,4 +93,4 @@ function parseImagePullPolicy(value) {
93
93
  return "Always";
94
94
  }
95
95
  //#endregion
96
- export { addMokaSubmitOptions, runMokaSubmitFromCli };
96
+ export { addMokaSubmitOptions, buildMokaSubmitInputFromCli, runMokaSubmitFromCli };
@@ -226,8 +226,8 @@ declare const configSchema: z.ZodObject<{
226
226
  policy: z.ZodOptional<z.ZodObject<{
227
227
  commands: z.ZodOptional<z.ZodEnum<{
228
228
  allow: "allow";
229
- "trusted-only": "trusted-only";
230
229
  deny: "deny";
230
+ "trusted-only": "trusted-only";
231
231
  }>>;
232
232
  modules: z.ZodOptional<z.ZodEnum<{
233
233
  allow: "allow";
@@ -255,8 +255,8 @@ declare const configSchema: z.ZodObject<{
255
255
  global: "global";
256
256
  }>>;
257
257
  mode: z.ZodEnum<{
258
- hosted: "hosted";
259
258
  local: "local";
259
+ hosted: "hosted";
260
260
  }>;
261
261
  provider: z.ZodLiteral<"toolhive">;
262
262
  authorization_env: z.ZodDefault<z.ZodString>;
@@ -300,10 +300,10 @@ declare const configSchema: z.ZodObject<{
300
300
  }, z.core.$strict>>;
301
301
  output: z.ZodOptional<z.ZodObject<{
302
302
  format: z.ZodEnum<{
303
+ json_schema: "json_schema";
303
304
  text: "text";
304
305
  json: "json";
305
306
  jsonl: "jsonl";
306
- json_schema: "json_schema";
307
307
  }>;
308
308
  repair: z.ZodOptional<z.ZodObject<{
309
309
  enabled: z.ZodOptional<z.ZodBoolean>;
@@ -379,10 +379,10 @@ declare const configSchema: z.ZodObject<{
379
379
  disabled: "disabled";
380
380
  }>>>;
381
381
  output_formats: z.ZodOptional<z.ZodArray<z.ZodEnum<{
382
+ json_schema: "json_schema";
382
383
  text: "text";
383
384
  json: "json";
384
385
  jsonl: "jsonl";
385
- json_schema: "json_schema";
386
386
  }>>>;
387
387
  rules: z.ZodOptional<z.ZodBoolean>;
388
388
  skills: z.ZodOptional<z.ZodBoolean>;
@@ -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 = [
@@ -1,7 +1,8 @@
1
+ import { resolveHarnessTarget } from "./install-commands/shared.js";
1
2
  import { AGENT_ASSET_SOURCE, AGENT_RULES_DIR } from "./agent-assets.js";
2
3
  import { execa } from "execa";
3
- import { homedir, tmpdir } from "node:os";
4
- import { join } from "node:path";
4
+ import { tmpdir } from "node:os";
5
+ import { dirname, join } from "node:path";
5
6
  import { mkdir, mkdtemp, readFile, readdir, rm, writeFile } from "node:fs/promises";
6
7
  //#region src/install-rules.ts
7
8
  const DEFAULT_RULES_INSTALL_SOURCE = AGENT_ASSET_SOURCE;
@@ -12,6 +13,24 @@ const RULESYNC_TARGETS = [
12
13
  "geminicli",
13
14
  "opencode"
14
15
  ];
16
+ const RULE_OUTPUTS = [
17
+ {
18
+ generatedPath: ".claude/CLAUDE.md",
19
+ targetPath: ".claude/CLAUDE.md"
20
+ },
21
+ {
22
+ generatedPath: ".codex/AGENTS.md",
23
+ targetPath: ".codex/AGENTS.md"
24
+ },
25
+ {
26
+ generatedPath: ".gemini/GEMINI.md",
27
+ targetPath: ".gemini/GEMINI.md"
28
+ },
29
+ {
30
+ generatedPath: ".config/opencode/AGENTS.md",
31
+ targetPath: ".opencode/AGENTS.md"
32
+ }
33
+ ];
15
34
  async function cloneRulesRepository(targetDir) {
16
35
  await execa("gh", [
17
36
  "repo",
@@ -71,50 +90,110 @@ ${(await Promise.all(entries.map(async (name) => {
71
90
  await mkdir(rulesyncRulesDir, { recursive: true });
72
91
  await writeFile(join(rulesyncRulesDir, "_root.md"), rootContent);
73
92
  }
93
+ async function withRulesyncHome(useHome) {
94
+ const home = await mkdtemp(join(tmpdir(), "moka-rules-home-"));
95
+ try {
96
+ return await useHome(home);
97
+ } finally {
98
+ await rm(home, {
99
+ force: true,
100
+ recursive: true
101
+ });
102
+ }
103
+ }
104
+ function rulesyncArgs(options) {
105
+ const args = [
106
+ "generate",
107
+ "-t",
108
+ RULESYNC_TARGETS.join(","),
109
+ "-f",
110
+ "rules",
111
+ "--delete",
112
+ "--global"
113
+ ];
114
+ if (options.dryRun) args.push("--dry-run");
115
+ if (options.silent) args.push("--silent");
116
+ return args;
117
+ }
118
+ async function runRulesyncGenerate(input) {
119
+ await input.runner(rulesyncArgs(input), {
120
+ cwd: input.source,
121
+ env: {
122
+ ...process.env,
123
+ HOME_DIR: input.home
124
+ }
125
+ });
126
+ }
127
+ function ruleItems(action) {
128
+ return RULE_OUTPUTS.map((output) => ({
129
+ action,
130
+ path: resolveHarnessTarget(output.targetPath)
131
+ }));
132
+ }
133
+ function readGeneratedRuleFiles(home) {
134
+ return Promise.all(RULE_OUTPUTS.map(async (output) => ({
135
+ content: await readFile(join(home, output.generatedPath), "utf8"),
136
+ path: resolveHarnessTarget(output.targetPath)
137
+ })));
138
+ }
139
+ async function writeGeneratedRuleFiles(files) {
140
+ for (const file of files) {
141
+ await mkdir(dirname(file.path), { recursive: true });
142
+ await writeFile(file.path, file.content);
143
+ }
144
+ }
145
+ async function installedRuleAction(file) {
146
+ try {
147
+ return await readFile(file.path, "utf8") === file.content ? "unchanged" : "update";
148
+ } catch {
149
+ return "create";
150
+ }
151
+ }
152
+ async function assertInstalledRulesCurrent(files) {
153
+ const changed = (await Promise.all(files.map(async (file) => ({
154
+ action: await installedRuleAction(file),
155
+ path: file.path
156
+ })))).filter((item) => item.action !== "unchanged");
157
+ if (changed.length === 0) return;
158
+ throw new Error(["Installed rule files are not up to date.", ...changed.map((item) => `- ${item.path}: ${item.action}`)].join("\n"));
159
+ }
74
160
  function installRules(options = {}) {
75
161
  const runner = options.rulesyncRunner ?? defaultRulesyncRunner;
76
162
  return withRulesSource(options.sourceOverride, async (source) => {
77
163
  await buildRootRule(source);
78
- const home = process.env.HOME_DIR ?? homedir();
79
- const args = [
80
- "generate",
81
- "-t",
82
- RULESYNC_TARGETS.join(","),
83
- "-f",
84
- "rules",
85
- "--delete"
86
- ];
87
- if (options.dryRun) args.push("--dry-run");
88
- if (options.check) args.push("--check");
89
- await runner(args, {
90
- cwd: source,
91
- env: {
92
- ...process.env,
93
- HOME_DIR: home
164
+ return withRulesyncHome(async (home) => {
165
+ if (options.dryRun) {
166
+ await runRulesyncGenerate({
167
+ dryRun: true,
168
+ home,
169
+ runner,
170
+ source
171
+ });
172
+ return {
173
+ items: ruleItems("skip"),
174
+ source: DEFAULT_RULES_INSTALL_SOURCE
175
+ };
176
+ }
177
+ await runRulesyncGenerate({
178
+ home,
179
+ runner,
180
+ silent: options.check,
181
+ source
182
+ });
183
+ const files = await readGeneratedRuleFiles(home);
184
+ if (options.check) {
185
+ await assertInstalledRulesCurrent(files);
186
+ return {
187
+ items: ruleItems("skip"),
188
+ source: DEFAULT_RULES_INSTALL_SOURCE
189
+ };
94
190
  }
191
+ await writeGeneratedRuleFiles(files);
192
+ return {
193
+ items: ruleItems("generate"),
194
+ source: DEFAULT_RULES_INSTALL_SOURCE
195
+ };
95
196
  });
96
- const action = options.dryRun ?? options.check ? "skip" : "generate";
97
- return {
98
- items: [
99
- {
100
- action,
101
- path: join(home, ".claude/CLAUDE.md")
102
- },
103
- {
104
- action,
105
- path: join(home, ".codex/AGENTS.md")
106
- },
107
- {
108
- action,
109
- path: join(home, ".gemini/GEMINI.md")
110
- },
111
- {
112
- action,
113
- path: join(home, ".config/opencode/AGENTS.md")
114
- }
115
- ],
116
- source: DEFAULT_RULES_INSTALL_SOURCE
117
- };
118
197
  });
119
198
  }
120
199
  //#endregion
@@ -1,3 +1,4 @@
1
+ import { Effect } from "effect";
1
2
  import { z } from "zod";
2
3
 
3
4
  //#region src/moka-global-config.d.ts
@@ -29,20 +30,24 @@ declare const mokaGlobalConfigSchema: z.ZodObject<{
29
30
  }, z.core.$strict>;
30
31
  type MokaGlobalConfig = z.infer<typeof mokaGlobalConfigSchema>;
31
32
  declare function mokaGlobalConfigPath(homeDir?: string): string;
33
+ declare class MokaDbUrlRequiredError extends Error {
34
+ readonly code = "db.url-required";
35
+ constructor();
36
+ }
37
+ declare function requireMokaDbUrl(dbUrl: string | undefined): Effect.Effect<string, MokaDbUrlRequiredError>;
32
38
  /**
33
39
  * Resolve the durable-substrate `db.url` toggle for run-control store selection.
34
40
  *
35
- * Returns the configured Postgres url, or `undefined` for the defined default
36
- * (filesystem store) when the global config is absent or carries no `db.url`.
41
+ * Returns the configured Postgres url, or `undefined` when the global config is
42
+ * absent or carries no `db.url`.
37
43
  * The whole `momokaya` schema is deliberately NOT validated — only the `db`
38
44
  * section is — so an unrelated invalid/missing field never breaks run-control
39
45
  * reads. A genuine load fault (corrupt YAML, a malformed `db.url`) is surfaced
40
- * to stderr and falls back to the filesystem store rather than crashing the
41
- * command; this is the presence-toggle's resilience, not silent error-swallowing
42
- * (the fault is always logged).
46
+ * to stderr and returns `undefined`; the required-DB policy then fails at the
47
+ * runtime-state boundary with `db.url-required`.
43
48
  */
44
49
  declare function loadMokaDbUrl(): string | undefined;
45
50
  declare function loadMokaGlobalConfig(): MokaGlobalConfig | null;
46
51
  declare function parseMokaGlobalConfig(source: string, sourcePath: string): MokaGlobalConfig;
47
52
  //#endregion
48
- export { MOKA_GLOBAL_CONFIG_PATH, MokaGlobalConfig, loadMokaDbUrl, loadMokaGlobalConfig, mokaGlobalConfigPath, mokaGlobalConfigSchema, parseMokaGlobalConfig };
53
+ export { MOKA_GLOBAL_CONFIG_PATH, MokaDbUrlRequiredError, MokaGlobalConfig, loadMokaDbUrl, loadMokaGlobalConfig, mokaGlobalConfigPath, mokaGlobalConfigSchema, parseMokaGlobalConfig, requireMokaDbUrl };
@@ -37,20 +37,39 @@ const mokaGlobalConfigSchema = z.object({ momokaya: z.object({
37
37
  function mokaGlobalConfigPath(homeDir = homedir()) {
38
38
  return join(homeDir, MOKA_GLOBAL_CONFIG_PATH);
39
39
  }
40
+ var MokaDbUrlRequiredError = class extends Error {
41
+ code = "db.url-required";
42
+ constructor() {
43
+ super(`db.url-required: momokaya.db.url is required for Moka run-control runtime state. Configure momokaya.db.url in ${MOKA_GLOBAL_CONFIG_PATH}.`);
44
+ this.name = "MokaDbUrlRequiredError";
45
+ }
46
+ };
47
+ function requireMokaDbUrl(dbUrl) {
48
+ if (dbUrl === void 0) return Effect.fail(new MokaDbUrlRequiredError());
49
+ return Effect.succeed(dbUrl);
50
+ }
40
51
  const mokaDbUrlReadSchema = z.object({ momokaya: z.object({ db: mokaDbGlobalConfigSchema.optional() }).optional() });
41
52
  /**
42
53
  * Resolve the durable-substrate `db.url` toggle for run-control store selection.
43
54
  *
44
- * Returns the configured Postgres url, or `undefined` for the defined default
45
- * (filesystem store) when the global config is absent or carries no `db.url`.
55
+ * Returns the configured Postgres url, or `undefined` when the global config is
56
+ * absent or carries no `db.url`.
46
57
  * The whole `momokaya` schema is deliberately NOT validated — only the `db`
47
58
  * section is — so an unrelated invalid/missing field never breaks run-control
48
59
  * reads. A genuine load fault (corrupt YAML, a malformed `db.url`) is surfaced
49
- * to stderr and falls back to the filesystem store rather than crashing the
50
- * command; this is the presence-toggle's resilience, not silent error-swallowing
51
- * (the fault is always logged).
60
+ * to stderr and returns `undefined`; the required-DB policy then fails at the
61
+ * runtime-state boundary with `db.url-required`.
52
62
  */
53
63
  function loadMokaDbUrl() {
64
+ const envUrl = process.env.MOKA_DB_URL;
65
+ if (envUrl !== void 0) {
66
+ const parsed = mokaDbGlobalConfigSchema.safeParse({ url: envUrl });
67
+ if (!parsed.success) {
68
+ process.stderr.write(`run-control: MOKA_DB_URL is invalid: ${parsed.error.message}\n`);
69
+ return;
70
+ }
71
+ return parsed.data.url;
72
+ }
54
73
  const configPath = mokaGlobalConfigPath();
55
74
  const program = Effect.gen(function* () {
56
75
  const configIo = yield* ConfigIoService;
@@ -93,4 +112,4 @@ function parseMokaGlobalConfigEffect(source, sourcePath) {
93
112
  });
94
113
  }
95
114
  //#endregion
96
- export { MOKA_GLOBAL_CONFIG_PATH, loadMokaDbUrl, loadMokaGlobalConfig, mokaGlobalConfigPath, mokaGlobalConfigSchema, parseMokaGlobalConfig };
115
+ export { MOKA_GLOBAL_CONFIG_PATH, MokaDbUrlRequiredError, loadMokaDbUrl, loadMokaGlobalConfig, mokaGlobalConfigPath, mokaGlobalConfigSchema, parseMokaGlobalConfig, requireMokaDbUrl };
@@ -106,6 +106,10 @@ declare const mokaSubmitBaseOptionsSchema: z.ZodObject<{
106
106
  secretName: z.ZodString;
107
107
  url: z.ZodDefault<z.ZodString>;
108
108
  }, z.core.$strict>;
109
+ dbAuth: z.ZodOptional<z.ZodObject<{
110
+ secretKey: z.ZodDefault<z.ZodString>;
111
+ secretName: z.ZodString;
112
+ }, z.core.$strict>>;
109
113
  delivery: z.ZodDefault<z.ZodObject<{
110
114
  mode: z.ZodDefault<z.ZodEnum<{
111
115
  "create-new-pr": "create-new-pr";
@@ -211,6 +215,10 @@ declare const mokaGraphSubmitOptionsSchema: z.ZodObject<{
211
215
  secretName: z.ZodString;
212
216
  url: z.ZodDefault<z.ZodString>;
213
217
  }, z.core.$strict>;
218
+ dbAuth: z.ZodOptional<z.ZodObject<{
219
+ secretKey: z.ZodDefault<z.ZodString>;
220
+ secretName: z.ZodString;
221
+ }, z.core.$strict>>;
214
222
  delivery: z.ZodDefault<z.ZodObject<{
215
223
  mode: z.ZodDefault<z.ZodEnum<{
216
224
  "create-new-pr": "create-new-pr";
@@ -333,6 +341,10 @@ declare const mokaCommandSubmitOptionsSchema: z.ZodObject<{
333
341
  secretName: z.ZodString;
334
342
  url: z.ZodDefault<z.ZodString>;
335
343
  }, z.core.$strict>;
344
+ dbAuth: z.ZodOptional<z.ZodObject<{
345
+ secretKey: z.ZodDefault<z.ZodString>;
346
+ secretName: z.ZodString;
347
+ }, z.core.$strict>>;
336
348
  delivery: z.ZodDefault<z.ZodObject<{
337
349
  mode: z.ZodDefault<z.ZodEnum<{
338
350
  "create-new-pr": "create-new-pr";
@@ -450,6 +462,10 @@ declare const mokaSubmitOptionsSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
450
462
  secretName: z.ZodString;
451
463
  url: z.ZodDefault<z.ZodString>;
452
464
  }, z.core.$strict>;
465
+ dbAuth: z.ZodOptional<z.ZodObject<{
466
+ secretKey: z.ZodDefault<z.ZodString>;
467
+ secretName: z.ZodString;
468
+ }, z.core.$strict>>;
453
469
  delivery: z.ZodDefault<z.ZodObject<{
454
470
  mode: z.ZodDefault<z.ZodEnum<{
455
471
  "create-new-pr": "create-new-pr";
@@ -571,6 +587,10 @@ declare const mokaSubmitOptionsSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
571
587
  secretName: z.ZodString;
572
588
  url: z.ZodDefault<z.ZodString>;
573
589
  }, z.core.$strict>;
590
+ dbAuth: z.ZodOptional<z.ZodObject<{
591
+ secretKey: z.ZodDefault<z.ZodString>;
592
+ secretName: z.ZodString;
593
+ }, z.core.$strict>>;
574
594
  delivery: z.ZodDefault<z.ZodObject<{
575
595
  mode: z.ZodDefault<z.ZodEnum<{
576
596
  "create-new-pr": "create-new-pr";
@@ -1,3 +1,4 @@
1
+ import { dbAuthOptionSchema } from "./remote/argo/model.js";
1
2
  import { brokerAuthOptionSchema } from "./credentials/broker.js";
2
3
  import { runnerDeliverySchema, runnerHookPolicySchema, runnerRepositoryContextSchema, runnerRunIdentitySchema, runnerTaskSchema } from "./runner-command-contract.js";
3
4
  import { workflowSubmitResultSchema } from "./workflow-submit-contract.js";
@@ -46,6 +47,7 @@ const mokaSubmitHookPolicySchema = runnerHookPolicySchema;
46
47
  const mokaSubmitResultSchema = workflowSubmitResultSchema;
47
48
  const mokaSubmitBaseOptionsSchema = z.object({
48
49
  brokerAuth: brokerAuthOptionSchema,
50
+ dbAuth: dbAuthOptionSchema.optional(),
49
51
  delivery: runnerDeliverySchema.default({
50
52
  mode: "create-new-pr",
51
53
  pullRequest: false
@@ -39,12 +39,8 @@ function hookInstallerFiles(result) {
39
39
  }
40
40
  async function initPipelineProject(options = {}) {
41
41
  const cwd = options.cwd ?? process.cwd();
42
- const { check, dryRun, force } = options;
43
- const installerFlags = {
44
- check,
45
- dryRun,
46
- force
47
- };
42
+ const { check, dryRun } = options;
43
+ const installerFlags = initInstallerFlags(options);
48
44
  if (!(check || dryRun)) await (options.skillInstaller ?? installDefaultSkills)(cwd);
49
45
  const result = await installCommands({
50
46
  cwd,
@@ -59,6 +55,14 @@ async function initPipelineProject(options = {}) {
59
55
  ...rulesResult.items.map((item) => item.path)
60
56
  ] };
61
57
  }
58
+ function initInstallerFlags(options) {
59
+ const { check, dryRun } = options;
60
+ return {
61
+ check,
62
+ dryRun,
63
+ force: options.force ?? !(check || dryRun)
64
+ };
65
+ }
62
66
  const INIT_RESULT_COPY = {
63
67
  install: {
64
68
  headline: "Initialized package-owned pipeline support:",